Changed CRLF to LF in .java base src files. Minor reformatting fixes.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@776377 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e6a53dc85b
commit
bae270a565
@ -1,276 +1,276 @@
|
||||
/*
|
||||
* 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.ddf;
|
||||
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
/**
|
||||
* @author Daniel Noll
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EscherPictBlip
|
||||
extends EscherBlipRecord
|
||||
{
|
||||
private static final POILogger log = POILogFactory.getLogger(EscherPictBlip.class);
|
||||
|
||||
public static final short RECORD_ID_EMF = (short) 0xF018 + 2;
|
||||
public static final short RECORD_ID_WMF = (short) 0xF018 + 3;
|
||||
public static final short RECORD_ID_PICT = (short) 0xF018 + 4;
|
||||
|
||||
private static final int HEADER_SIZE = 8;
|
||||
|
||||
private byte[] field_1_UID;
|
||||
private int field_2_cb;
|
||||
private int field_3_rcBounds_x1;
|
||||
private int field_3_rcBounds_y1;
|
||||
private int field_3_rcBounds_x2;
|
||||
private int field_3_rcBounds_y2;
|
||||
private int field_4_ptSize_w;
|
||||
private int field_4_ptSize_h;
|
||||
private int field_5_cbSave;
|
||||
private byte field_6_fCompression;
|
||||
private byte field_7_fFilter;
|
||||
|
||||
private byte[] raw_pictureData;
|
||||
|
||||
/**
|
||||
* This method deserializes the record from a byte array.
|
||||
*
|
||||
* @param data The byte array containing the escher record information
|
||||
* @param offset The starting offset into <code>data</code>.
|
||||
* @param recordFactory May be null since this is not a container record.
|
||||
* @return The number of bytes read from the byte array.
|
||||
*/
|
||||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory )
|
||||
{
|
||||
int bytesAfterHeader = readHeader( data, offset );
|
||||
int pos = offset + HEADER_SIZE;
|
||||
|
||||
field_1_UID = new byte[16];
|
||||
System.arraycopy( data, pos, field_1_UID, 0, 16 ); pos += 16;
|
||||
field_2_cb = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_3_rcBounds_x1 = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_3_rcBounds_y1 = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_3_rcBounds_x2 = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_3_rcBounds_y2 = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_4_ptSize_w = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_4_ptSize_h = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_5_cbSave = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_6_fCompression = data[pos]; pos++;
|
||||
field_7_fFilter = data[pos]; pos++;
|
||||
|
||||
raw_pictureData = new byte[field_5_cbSave];
|
||||
System.arraycopy( data, pos, raw_pictureData, 0, field_5_cbSave );
|
||||
|
||||
// 0 means DEFLATE compression
|
||||
// 0xFE means no compression
|
||||
if (field_6_fCompression == 0)
|
||||
{
|
||||
field_pictureData = inflatePictureData(raw_pictureData);
|
||||
}
|
||||
else
|
||||
{
|
||||
field_pictureData = raw_pictureData;
|
||||
}
|
||||
|
||||
return bytesAfterHeader + HEADER_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the record to an existing byte array.
|
||||
*
|
||||
* @param offset the offset within the byte array
|
||||
* @param data the data array to serialize to
|
||||
* @param listener a listener for begin and end serialization events. This
|
||||
* is useful because the serialization is
|
||||
* hierarchical/recursive and sometimes you need to be able
|
||||
* break into that.
|
||||
* @return the number of bytes written.
|
||||
*/
|
||||
public int serialize( int offset, byte[] data, EscherSerializationListener listener )
|
||||
{
|
||||
listener.beforeRecordSerialize(offset, getRecordId(), this);
|
||||
|
||||
int pos = offset;
|
||||
LittleEndian.putShort( data, pos, getOptions() ); pos += 2;
|
||||
LittleEndian.putShort( data, pos, getRecordId() ); pos += 2;
|
||||
LittleEndian.putInt( data, getRecordSize() - HEADER_SIZE ); pos += 4;
|
||||
|
||||
System.arraycopy( field_1_UID, 0, data, pos, 16 ); pos += 16;
|
||||
LittleEndian.putInt( data, pos, field_2_cb ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_rcBounds_x1 ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_rcBounds_y1 ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_rcBounds_x2 ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_rcBounds_y2 ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_4_ptSize_w ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_4_ptSize_h ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_5_cbSave ); pos += 4;
|
||||
data[pos] = field_6_fCompression; pos++;
|
||||
data[pos] = field_7_fFilter; pos++;
|
||||
|
||||
System.arraycopy( raw_pictureData, 0, data, pos, raw_pictureData.length );
|
||||
|
||||
listener.afterRecordSerialize(offset + getRecordSize(), getRecordId(), getRecordSize(), this);
|
||||
return HEADER_SIZE + 16 + 1 + raw_pictureData.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompresses the provided data, returning the inflated result.
|
||||
*
|
||||
* @param data the deflated picture data.
|
||||
* @return the inflated picture data.
|
||||
*/
|
||||
private static byte[] inflatePictureData(byte[] data)
|
||||
{
|
||||
try
|
||||
{
|
||||
InflaterInputStream in = new InflaterInputStream(
|
||||
new ByteArrayInputStream( data ) );
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[4096];
|
||||
int readBytes;
|
||||
while ((readBytes = in.read(buf)) > 0)
|
||||
{
|
||||
out.write(buf, 0, readBytes);
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
log.log(POILogger.INFO, "Possibly corrupt compression or non-compressed data", e);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that are required to serialize this record.
|
||||
*
|
||||
* @return Number of bytes
|
||||
*/
|
||||
public int getRecordSize()
|
||||
{
|
||||
return 8 + 50 + raw_pictureData.length;
|
||||
}
|
||||
|
||||
public byte[] getUID()
|
||||
{
|
||||
return field_1_UID;
|
||||
}
|
||||
|
||||
public void setUID( byte[] field_1_UID )
|
||||
{
|
||||
this.field_1_UID = field_1_UID;
|
||||
}
|
||||
|
||||
public int getUncompressedSize()
|
||||
{
|
||||
return field_2_cb;
|
||||
}
|
||||
|
||||
public void setUncompressedSize(int uncompressedSize)
|
||||
{
|
||||
field_2_cb = uncompressedSize;
|
||||
}
|
||||
|
||||
public Rectangle getBounds()
|
||||
{
|
||||
return new Rectangle(field_3_rcBounds_x1,
|
||||
field_3_rcBounds_y1,
|
||||
field_3_rcBounds_x2 - field_3_rcBounds_x1,
|
||||
field_3_rcBounds_y2 - field_3_rcBounds_y1);
|
||||
}
|
||||
|
||||
public void setBounds(Rectangle bounds)
|
||||
{
|
||||
field_3_rcBounds_x1 = bounds.x;
|
||||
field_3_rcBounds_y1 = bounds.y;
|
||||
field_3_rcBounds_x2 = bounds.x + bounds.width;
|
||||
field_3_rcBounds_y2 = bounds.y + bounds.height;
|
||||
}
|
||||
|
||||
public Dimension getSizeEMU()
|
||||
{
|
||||
return new Dimension(field_4_ptSize_w, field_4_ptSize_h);
|
||||
}
|
||||
|
||||
public void setSizeEMU(Dimension sizeEMU)
|
||||
{
|
||||
field_4_ptSize_w = sizeEMU.width;
|
||||
field_4_ptSize_h = sizeEMU.height;
|
||||
}
|
||||
|
||||
public int getCompressedSize()
|
||||
{
|
||||
return field_5_cbSave;
|
||||
}
|
||||
|
||||
public void setCompressedSize(int compressedSize)
|
||||
{
|
||||
field_5_cbSave = compressedSize;
|
||||
}
|
||||
|
||||
public boolean isCompressed()
|
||||
{
|
||||
return (field_6_fCompression == 0);
|
||||
}
|
||||
|
||||
public void setCompressed(boolean compressed)
|
||||
{
|
||||
field_6_fCompression = compressed ? 0 : (byte)0xFE;
|
||||
}
|
||||
|
||||
// filtering is always 254 according to available docs, so no point giving it a setter method.
|
||||
|
||||
public String toString()
|
||||
{
|
||||
String nl = System.getProperty( "line.separator" );
|
||||
|
||||
String extraData;
|
||||
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
HexDump.dump( this.field_pictureData, 0, b, 0 );
|
||||
extraData = b.toString();
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
extraData = e.toString();
|
||||
}
|
||||
return getClass().getName() + ":" + nl +
|
||||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl +
|
||||
" Options: 0x" + HexDump.toHex( getOptions() ) + nl +
|
||||
" UID: 0x" + HexDump.toHex( field_1_UID ) + nl +
|
||||
" Uncompressed Size: " + HexDump.toHex( field_2_cb ) + nl +
|
||||
" Bounds: " + getBounds() + nl +
|
||||
" Size in EMU: " + getSizeEMU() + nl +
|
||||
" Compressed Size: " + HexDump.toHex( field_5_cbSave ) + nl +
|
||||
" Compression: " + HexDump.toHex( field_6_fCompression ) + nl +
|
||||
" Filter: " + HexDump.toHex( field_7_fFilter ) + nl +
|
||||
" Extra Data:" + nl + extraData;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.ddf;
|
||||
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
/**
|
||||
* @author Daniel Noll
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EscherPictBlip
|
||||
extends EscherBlipRecord
|
||||
{
|
||||
private static final POILogger log = POILogFactory.getLogger(EscherPictBlip.class);
|
||||
|
||||
public static final short RECORD_ID_EMF = (short) 0xF018 + 2;
|
||||
public static final short RECORD_ID_WMF = (short) 0xF018 + 3;
|
||||
public static final short RECORD_ID_PICT = (short) 0xF018 + 4;
|
||||
|
||||
private static final int HEADER_SIZE = 8;
|
||||
|
||||
private byte[] field_1_UID;
|
||||
private int field_2_cb;
|
||||
private int field_3_rcBounds_x1;
|
||||
private int field_3_rcBounds_y1;
|
||||
private int field_3_rcBounds_x2;
|
||||
private int field_3_rcBounds_y2;
|
||||
private int field_4_ptSize_w;
|
||||
private int field_4_ptSize_h;
|
||||
private int field_5_cbSave;
|
||||
private byte field_6_fCompression;
|
||||
private byte field_7_fFilter;
|
||||
|
||||
private byte[] raw_pictureData;
|
||||
|
||||
/**
|
||||
* This method deserializes the record from a byte array.
|
||||
*
|
||||
* @param data The byte array containing the escher record information
|
||||
* @param offset The starting offset into <code>data</code>.
|
||||
* @param recordFactory May be null since this is not a container record.
|
||||
* @return The number of bytes read from the byte array.
|
||||
*/
|
||||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory )
|
||||
{
|
||||
int bytesAfterHeader = readHeader( data, offset );
|
||||
int pos = offset + HEADER_SIZE;
|
||||
|
||||
field_1_UID = new byte[16];
|
||||
System.arraycopy( data, pos, field_1_UID, 0, 16 ); pos += 16;
|
||||
field_2_cb = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_3_rcBounds_x1 = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_3_rcBounds_y1 = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_3_rcBounds_x2 = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_3_rcBounds_y2 = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_4_ptSize_w = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_4_ptSize_h = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_5_cbSave = LittleEndian.getInt( data, pos ); pos += 4;
|
||||
field_6_fCompression = data[pos]; pos++;
|
||||
field_7_fFilter = data[pos]; pos++;
|
||||
|
||||
raw_pictureData = new byte[field_5_cbSave];
|
||||
System.arraycopy( data, pos, raw_pictureData, 0, field_5_cbSave );
|
||||
|
||||
// 0 means DEFLATE compression
|
||||
// 0xFE means no compression
|
||||
if (field_6_fCompression == 0)
|
||||
{
|
||||
field_pictureData = inflatePictureData(raw_pictureData);
|
||||
}
|
||||
else
|
||||
{
|
||||
field_pictureData = raw_pictureData;
|
||||
}
|
||||
|
||||
return bytesAfterHeader + HEADER_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the record to an existing byte array.
|
||||
*
|
||||
* @param offset the offset within the byte array
|
||||
* @param data the data array to serialize to
|
||||
* @param listener a listener for begin and end serialization events. This
|
||||
* is useful because the serialization is
|
||||
* hierarchical/recursive and sometimes you need to be able
|
||||
* break into that.
|
||||
* @return the number of bytes written.
|
||||
*/
|
||||
public int serialize( int offset, byte[] data, EscherSerializationListener listener )
|
||||
{
|
||||
listener.beforeRecordSerialize(offset, getRecordId(), this);
|
||||
|
||||
int pos = offset;
|
||||
LittleEndian.putShort( data, pos, getOptions() ); pos += 2;
|
||||
LittleEndian.putShort( data, pos, getRecordId() ); pos += 2;
|
||||
LittleEndian.putInt( data, getRecordSize() - HEADER_SIZE ); pos += 4;
|
||||
|
||||
System.arraycopy( field_1_UID, 0, data, pos, 16 ); pos += 16;
|
||||
LittleEndian.putInt( data, pos, field_2_cb ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_rcBounds_x1 ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_rcBounds_y1 ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_rcBounds_x2 ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_rcBounds_y2 ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_4_ptSize_w ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_4_ptSize_h ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_5_cbSave ); pos += 4;
|
||||
data[pos] = field_6_fCompression; pos++;
|
||||
data[pos] = field_7_fFilter; pos++;
|
||||
|
||||
System.arraycopy( raw_pictureData, 0, data, pos, raw_pictureData.length );
|
||||
|
||||
listener.afterRecordSerialize(offset + getRecordSize(), getRecordId(), getRecordSize(), this);
|
||||
return HEADER_SIZE + 16 + 1 + raw_pictureData.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompresses the provided data, returning the inflated result.
|
||||
*
|
||||
* @param data the deflated picture data.
|
||||
* @return the inflated picture data.
|
||||
*/
|
||||
private static byte[] inflatePictureData(byte[] data)
|
||||
{
|
||||
try
|
||||
{
|
||||
InflaterInputStream in = new InflaterInputStream(
|
||||
new ByteArrayInputStream( data ) );
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[4096];
|
||||
int readBytes;
|
||||
while ((readBytes = in.read(buf)) > 0)
|
||||
{
|
||||
out.write(buf, 0, readBytes);
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
log.log(POILogger.INFO, "Possibly corrupt compression or non-compressed data", e);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that are required to serialize this record.
|
||||
*
|
||||
* @return Number of bytes
|
||||
*/
|
||||
public int getRecordSize()
|
||||
{
|
||||
return 8 + 50 + raw_pictureData.length;
|
||||
}
|
||||
|
||||
public byte[] getUID()
|
||||
{
|
||||
return field_1_UID;
|
||||
}
|
||||
|
||||
public void setUID( byte[] field_1_UID )
|
||||
{
|
||||
this.field_1_UID = field_1_UID;
|
||||
}
|
||||
|
||||
public int getUncompressedSize()
|
||||
{
|
||||
return field_2_cb;
|
||||
}
|
||||
|
||||
public void setUncompressedSize(int uncompressedSize)
|
||||
{
|
||||
field_2_cb = uncompressedSize;
|
||||
}
|
||||
|
||||
public Rectangle getBounds()
|
||||
{
|
||||
return new Rectangle(field_3_rcBounds_x1,
|
||||
field_3_rcBounds_y1,
|
||||
field_3_rcBounds_x2 - field_3_rcBounds_x1,
|
||||
field_3_rcBounds_y2 - field_3_rcBounds_y1);
|
||||
}
|
||||
|
||||
public void setBounds(Rectangle bounds)
|
||||
{
|
||||
field_3_rcBounds_x1 = bounds.x;
|
||||
field_3_rcBounds_y1 = bounds.y;
|
||||
field_3_rcBounds_x2 = bounds.x + bounds.width;
|
||||
field_3_rcBounds_y2 = bounds.y + bounds.height;
|
||||
}
|
||||
|
||||
public Dimension getSizeEMU()
|
||||
{
|
||||
return new Dimension(field_4_ptSize_w, field_4_ptSize_h);
|
||||
}
|
||||
|
||||
public void setSizeEMU(Dimension sizeEMU)
|
||||
{
|
||||
field_4_ptSize_w = sizeEMU.width;
|
||||
field_4_ptSize_h = sizeEMU.height;
|
||||
}
|
||||
|
||||
public int getCompressedSize()
|
||||
{
|
||||
return field_5_cbSave;
|
||||
}
|
||||
|
||||
public void setCompressedSize(int compressedSize)
|
||||
{
|
||||
field_5_cbSave = compressedSize;
|
||||
}
|
||||
|
||||
public boolean isCompressed()
|
||||
{
|
||||
return (field_6_fCompression == 0);
|
||||
}
|
||||
|
||||
public void setCompressed(boolean compressed)
|
||||
{
|
||||
field_6_fCompression = compressed ? 0 : (byte)0xFE;
|
||||
}
|
||||
|
||||
// filtering is always 254 according to available docs, so no point giving it a setter method.
|
||||
|
||||
public String toString()
|
||||
{
|
||||
String nl = System.getProperty( "line.separator" );
|
||||
|
||||
String extraData;
|
||||
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
HexDump.dump( this.field_pictureData, 0, b, 0 );
|
||||
extraData = b.toString();
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
extraData = e.toString();
|
||||
}
|
||||
return getClass().getName() + ":" + nl +
|
||||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl +
|
||||
" Options: 0x" + HexDump.toHex( getOptions() ) + nl +
|
||||
" UID: 0x" + HexDump.toHex( field_1_UID ) + nl +
|
||||
" Uncompressed Size: " + HexDump.toHex( field_2_cb ) + nl +
|
||||
" Bounds: " + getBounds() + nl +
|
||||
" Size in EMU: " + getSizeEMU() + nl +
|
||||
" Compressed Size: " + HexDump.toHex( field_5_cbSave ) + nl +
|
||||
" Compression: " + HexDump.toHex( field_6_fCompression ) + nl +
|
||||
" Filter: " + HexDump.toHex( field_7_fFilter ) + nl +
|
||||
" Extra Data:" + nl + extraData;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,82 +1,82 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.model;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaParser;
|
||||
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaRenderer;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
|
||||
/**
|
||||
* HSSF wrapper for the {@link FormulaParser} and {@link FormulaRenderer}
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class HSSFFormulaParser {
|
||||
|
||||
private static FormulaParsingWorkbook createParsingWorkbook(HSSFWorkbook book) {
|
||||
return HSSFEvaluationWorkbook.create(book);
|
||||
}
|
||||
|
||||
private HSSFFormulaParser() {
|
||||
// no instances of this class
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for parsing cell formulas. see {@link #parse(String, HSSFWorkbook, int)}
|
||||
*/
|
||||
public static Ptg[] parse(String formula, HSSFWorkbook workbook) {
|
||||
return parse(formula, workbook, FormulaType.CELL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param formulaType a constant from {@link FormulaType}
|
||||
* @return the parsed formula tokens
|
||||
*/
|
||||
public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType) {
|
||||
return parse(formula, workbook, formulaType, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param formula the formula to parse
|
||||
* @param workbook the parent workbook
|
||||
* @param formulaType a constant from {@link FormulaType}
|
||||
* @param sheetIndex the 0-based index of the sheet this formula belongs to.
|
||||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means that
|
||||
* the scope of the name will be ignored and the parser will match named ranges only by name
|
||||
*
|
||||
* @return the parsed formula tokens
|
||||
*/
|
||||
public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType, int sheetIndex) {
|
||||
return FormulaParser.parse(formula, createParsingWorkbook(workbook), formulaType, sheetIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static method to convert an array of {@link Ptg}s in RPN order
|
||||
* to a human readable string format in infix mode.
|
||||
* @param book used for defined names and 3D references
|
||||
* @param ptgs must not be <code>null</code>
|
||||
* @return a human readable String
|
||||
*/
|
||||
public static String toFormulaString(HSSFWorkbook book, Ptg[] ptgs) {
|
||||
return FormulaRenderer.toFormulaString(HSSFEvaluationWorkbook.create(book), ptgs);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.model;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaParser;
|
||||
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaRenderer;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
|
||||
/**
|
||||
* HSSF wrapper for the {@link FormulaParser} and {@link FormulaRenderer}
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class HSSFFormulaParser {
|
||||
|
||||
private static FormulaParsingWorkbook createParsingWorkbook(HSSFWorkbook book) {
|
||||
return HSSFEvaluationWorkbook.create(book);
|
||||
}
|
||||
|
||||
private HSSFFormulaParser() {
|
||||
// no instances of this class
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for parsing cell formulas. see {@link #parse(String, HSSFWorkbook, int)}
|
||||
*/
|
||||
public static Ptg[] parse(String formula, HSSFWorkbook workbook) {
|
||||
return parse(formula, workbook, FormulaType.CELL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param formulaType a constant from {@link FormulaType}
|
||||
* @return the parsed formula tokens
|
||||
*/
|
||||
public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType) {
|
||||
return parse(formula, workbook, formulaType, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param formula the formula to parse
|
||||
* @param workbook the parent workbook
|
||||
* @param formulaType a constant from {@link FormulaType}
|
||||
* @param sheetIndex the 0-based index of the sheet this formula belongs to.
|
||||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means that
|
||||
* the scope of the name will be ignored and the parser will match named ranges only by name
|
||||
*
|
||||
* @return the parsed formula tokens
|
||||
*/
|
||||
public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType, int sheetIndex) {
|
||||
return FormulaParser.parse(formula, createParsingWorkbook(workbook), formulaType, sheetIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static method to convert an array of {@link Ptg}s in RPN order
|
||||
* to a human readable string format in infix mode.
|
||||
* @param book used for defined names and 3D references
|
||||
* @param ptgs must not be <code>null</code>
|
||||
* @return a human readable String
|
||||
*/
|
||||
public static String toFormulaString(HSSFWorkbook book, Ptg[] ptgs) {
|
||||
return FormulaRenderer.toFormulaString(HSSFEvaluationWorkbook.create(book), ptgs);
|
||||
}
|
||||
}
|
||||
|
@ -1,87 +1,87 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.ss.formula.Formula;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* ARRAY (0x0221)<p/>
|
||||
*
|
||||
* Treated in a similar way to SharedFormulaRecord
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ArrayRecord extends SharedValueRecordBase {
|
||||
|
||||
public final static short sid = 0x0221;
|
||||
private static final int OPT_ALWAYS_RECALCULATE = 0x0001;
|
||||
private static final int OPT_CALCULATE_ON_OPEN = 0x0002;
|
||||
|
||||
private int _options;
|
||||
private int _field3notUsed;
|
||||
private Formula _formula;
|
||||
|
||||
public ArrayRecord(RecordInputStream in) {
|
||||
super(in);
|
||||
_options = in.readUShort();
|
||||
_field3notUsed = in.readInt();
|
||||
int formulaTokenLen = in.readUShort();
|
||||
int totalFormulaLen = in.available();
|
||||
_formula = Formula.read(formulaTokenLen, in, totalFormulaLen);
|
||||
}
|
||||
|
||||
public boolean isAlwaysRecalculate() {
|
||||
return (_options & OPT_ALWAYS_RECALCULATE) != 0;
|
||||
}
|
||||
public boolean isCalculateOnOpen() {
|
||||
return (_options & OPT_CALCULATE_ON_OPEN) != 0;
|
||||
}
|
||||
|
||||
protected int getExtraDataSize() {
|
||||
return 2 + 4
|
||||
+ _formula.getEncodedSize();
|
||||
}
|
||||
protected void serializeExtraData(LittleEndianOutput out) {
|
||||
out.writeShort(_options);
|
||||
out.writeInt(_field3notUsed);
|
||||
_formula.serialize(out);
|
||||
}
|
||||
|
||||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName()).append(" [ARRAY]\n");
|
||||
sb.append(" range=").append(getRange().toString()).append("\n");
|
||||
sb.append(" options=").append(HexDump.shortToHex(_options)).append("\n");
|
||||
sb.append(" notUsed=").append(HexDump.intToHex(_field3notUsed)).append("\n");
|
||||
sb.append(" formula:").append("\n");
|
||||
Ptg[] ptgs = _formula.getTokens();
|
||||
for (int i = 0; i < ptgs.length; i++) {
|
||||
Ptg ptg = ptgs[i];
|
||||
sb.append(ptg.toString()).append(ptg.getRVAType()).append("\n");
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.ss.formula.Formula;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* ARRAY (0x0221)<p/>
|
||||
*
|
||||
* Treated in a similar way to SharedFormulaRecord
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ArrayRecord extends SharedValueRecordBase {
|
||||
|
||||
public final static short sid = 0x0221;
|
||||
private static final int OPT_ALWAYS_RECALCULATE = 0x0001;
|
||||
private static final int OPT_CALCULATE_ON_OPEN = 0x0002;
|
||||
|
||||
private int _options;
|
||||
private int _field3notUsed;
|
||||
private Formula _formula;
|
||||
|
||||
public ArrayRecord(RecordInputStream in) {
|
||||
super(in);
|
||||
_options = in.readUShort();
|
||||
_field3notUsed = in.readInt();
|
||||
int formulaTokenLen = in.readUShort();
|
||||
int totalFormulaLen = in.available();
|
||||
_formula = Formula.read(formulaTokenLen, in, totalFormulaLen);
|
||||
}
|
||||
|
||||
public boolean isAlwaysRecalculate() {
|
||||
return (_options & OPT_ALWAYS_RECALCULATE) != 0;
|
||||
}
|
||||
public boolean isCalculateOnOpen() {
|
||||
return (_options & OPT_CALCULATE_ON_OPEN) != 0;
|
||||
}
|
||||
|
||||
protected int getExtraDataSize() {
|
||||
return 2 + 4
|
||||
+ _formula.getEncodedSize();
|
||||
}
|
||||
protected void serializeExtraData(LittleEndianOutput out) {
|
||||
out.writeShort(_options);
|
||||
out.writeInt(_field3notUsed);
|
||||
_formula.serialize(out);
|
||||
}
|
||||
|
||||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName()).append(" [ARRAY]\n");
|
||||
sb.append(" range=").append(getRange().toString()).append("\n");
|
||||
sb.append(" options=").append(HexDump.shortToHex(_options)).append("\n");
|
||||
sb.append(" notUsed=").append(HexDump.intToHex(_field3notUsed)).append("\n");
|
||||
sb.append(" formula:").append("\n");
|
||||
Ptg[] ptgs = _formula.getTokens();
|
||||
for (int i = 0; i < ptgs.length; i++) {
|
||||
Ptg ptg = ptgs[i];
|
||||
sb.append(ptg.toString()).append(ptg.getRVAType()).append("\n");
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,132 +1,132 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Base class for all cell value records (implementors of {@link CellValueRecordInterface}).
|
||||
* Subclasses are expected to manage the cell data values (of various types).
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class CellRecord extends StandardRecord implements CellValueRecordInterface {
|
||||
private int _rowIndex;
|
||||
private int _columnIndex;
|
||||
private int _formatIndex;
|
||||
|
||||
protected CellRecord() {
|
||||
// fields uninitialised
|
||||
}
|
||||
|
||||
protected CellRecord(RecordInputStream in) {
|
||||
_rowIndex = in.readUShort();
|
||||
_columnIndex = in.readUShort();
|
||||
_formatIndex = in.readUShort();
|
||||
}
|
||||
|
||||
public final void setRow(int row) {
|
||||
_rowIndex = row;
|
||||
}
|
||||
|
||||
public final void setColumn(short col) {
|
||||
_columnIndex = col;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the index to the ExtendedFormat
|
||||
*
|
||||
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
|
||||
* @param xf index to the XF record
|
||||
*/
|
||||
public final void setXFIndex(short xf) {
|
||||
_formatIndex = xf;
|
||||
}
|
||||
|
||||
public final int getRow() {
|
||||
return _rowIndex;
|
||||
}
|
||||
|
||||
public final short getColumn() {
|
||||
return (short) _columnIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the index to the ExtendedFormat
|
||||
*
|
||||
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
|
||||
* @return index to the XF record
|
||||
*/
|
||||
public final short getXFIndex() {
|
||||
return (short) _formatIndex;
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String recordName = getRecordName();
|
||||
|
||||
sb.append("[").append(recordName).append("]\n");
|
||||
sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
|
||||
sb.append(" .col = ").append(HexDump.shortToHex(getColumn())).append("\n");
|
||||
sb.append(" .xfindex= ").append(HexDump.shortToHex(getXFIndex())).append("\n");
|
||||
appendValueText(sb);
|
||||
sb.append("\n");
|
||||
sb.append("[/").append(recordName).append("]\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append specific debug info (used by {@link #toString()} for the value
|
||||
* contained in this record. Trailing new-line should not be appended
|
||||
* (superclass does that).
|
||||
*/
|
||||
protected abstract void appendValueText(StringBuilder sb);
|
||||
|
||||
/**
|
||||
* Gets the debug info BIFF record type name (used by {@link #toString()}.
|
||||
*/
|
||||
protected abstract String getRecordName();
|
||||
|
||||
/**
|
||||
* writes out the value data for this cell record
|
||||
*/
|
||||
protected abstract void serializeValue(LittleEndianOutput out);
|
||||
|
||||
/**
|
||||
* @return the size (in bytes) of the value data for this cell record
|
||||
*/
|
||||
protected abstract int getValueDataSize();
|
||||
|
||||
public final void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(getRow());
|
||||
out.writeShort(getColumn());
|
||||
out.writeShort(getXFIndex());
|
||||
serializeValue(out);
|
||||
}
|
||||
|
||||
protected final int getDataSize() {
|
||||
return 6 + getValueDataSize();
|
||||
}
|
||||
|
||||
protected final void copyBaseFields(CellRecord rec) {
|
||||
rec._rowIndex = _rowIndex;
|
||||
rec._columnIndex = _columnIndex;
|
||||
rec._formatIndex = _formatIndex;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Base class for all cell value records (implementors of {@link CellValueRecordInterface}).
|
||||
* Subclasses are expected to manage the cell data values (of various types).
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class CellRecord extends StandardRecord implements CellValueRecordInterface {
|
||||
private int _rowIndex;
|
||||
private int _columnIndex;
|
||||
private int _formatIndex;
|
||||
|
||||
protected CellRecord() {
|
||||
// fields uninitialised
|
||||
}
|
||||
|
||||
protected CellRecord(RecordInputStream in) {
|
||||
_rowIndex = in.readUShort();
|
||||
_columnIndex = in.readUShort();
|
||||
_formatIndex = in.readUShort();
|
||||
}
|
||||
|
||||
public final void setRow(int row) {
|
||||
_rowIndex = row;
|
||||
}
|
||||
|
||||
public final void setColumn(short col) {
|
||||
_columnIndex = col;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the index to the ExtendedFormat
|
||||
*
|
||||
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
|
||||
* @param xf index to the XF record
|
||||
*/
|
||||
public final void setXFIndex(short xf) {
|
||||
_formatIndex = xf;
|
||||
}
|
||||
|
||||
public final int getRow() {
|
||||
return _rowIndex;
|
||||
}
|
||||
|
||||
public final short getColumn() {
|
||||
return (short) _columnIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the index to the ExtendedFormat
|
||||
*
|
||||
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
|
||||
* @return index to the XF record
|
||||
*/
|
||||
public final short getXFIndex() {
|
||||
return (short) _formatIndex;
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String recordName = getRecordName();
|
||||
|
||||
sb.append("[").append(recordName).append("]\n");
|
||||
sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
|
||||
sb.append(" .col = ").append(HexDump.shortToHex(getColumn())).append("\n");
|
||||
sb.append(" .xfindex= ").append(HexDump.shortToHex(getXFIndex())).append("\n");
|
||||
appendValueText(sb);
|
||||
sb.append("\n");
|
||||
sb.append("[/").append(recordName).append("]\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append specific debug info (used by {@link #toString()} for the value
|
||||
* contained in this record. Trailing new-line should not be appended
|
||||
* (superclass does that).
|
||||
*/
|
||||
protected abstract void appendValueText(StringBuilder sb);
|
||||
|
||||
/**
|
||||
* Gets the debug info BIFF record type name (used by {@link #toString()}.
|
||||
*/
|
||||
protected abstract String getRecordName();
|
||||
|
||||
/**
|
||||
* writes out the value data for this cell record
|
||||
*/
|
||||
protected abstract void serializeValue(LittleEndianOutput out);
|
||||
|
||||
/**
|
||||
* @return the size (in bytes) of the value data for this cell record
|
||||
*/
|
||||
protected abstract int getValueDataSize();
|
||||
|
||||
public final void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(getRow());
|
||||
out.writeShort(getColumn());
|
||||
out.writeShort(getXFIndex());
|
||||
serializeValue(out);
|
||||
}
|
||||
|
||||
protected final int getDataSize() {
|
||||
return 6 + getValueDataSize();
|
||||
}
|
||||
|
||||
protected final void copyBaseFields(CellRecord rec) {
|
||||
rec._rowIndex = _rowIndex;
|
||||
rec._columnIndex = _columnIndex;
|
||||
rec._formatIndex = _formatIndex;
|
||||
}
|
||||
}
|
||||
|
@ -1,109 +1,109 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Common header/footer base class
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
abstract class HeaderFooterBase extends StandardRecord {
|
||||
private boolean field_2_hasMultibyte;
|
||||
private String field_3_text;
|
||||
|
||||
protected HeaderFooterBase(String text) {
|
||||
setText(text);
|
||||
}
|
||||
|
||||
protected HeaderFooterBase(RecordInputStream in) {
|
||||
if (in.remaining() > 0) {
|
||||
int field_1_footer_len = in.readShort();
|
||||
field_2_hasMultibyte = in.readByte() != 0x00;
|
||||
|
||||
if (field_2_hasMultibyte) {
|
||||
field_3_text = in.readUnicodeLEString(field_1_footer_len);
|
||||
} else {
|
||||
field_3_text = in.readCompressedUnicode(field_1_footer_len);
|
||||
}
|
||||
} else {
|
||||
// Note - this is unusual: when the text is empty string, the whole record is empty (just the 4 byte BIFF header)
|
||||
field_3_text = "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set the footer string
|
||||
*
|
||||
* @param text string to display
|
||||
*/
|
||||
public final void setText(String text) {
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text must not be null");
|
||||
}
|
||||
field_2_hasMultibyte = StringUtil.hasMultibyte(text);
|
||||
field_3_text = text;
|
||||
|
||||
// Check it'll fit into the space in the record
|
||||
if (field_2_hasMultibyte) {
|
||||
if (field_3_text.length() > 127) {
|
||||
throw new IllegalArgumentException(
|
||||
"Footer string too long (limit is 127 for unicode strings)");
|
||||
}
|
||||
} else {
|
||||
if (field_3_text.length() > 255) {
|
||||
throw new IllegalArgumentException(
|
||||
"Footer string too long (limit is 255 for non-unicode strings)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the length of the footer string
|
||||
*
|
||||
* @return length of the footer string
|
||||
*/
|
||||
private int getTextLength() {
|
||||
return field_3_text.length();
|
||||
}
|
||||
|
||||
public final String getText() {
|
||||
return field_3_text;
|
||||
}
|
||||
|
||||
public final void serialize(LittleEndianOutput out) {
|
||||
if (getTextLength() > 0) {
|
||||
out.writeShort(getTextLength());
|
||||
out.writeByte(field_2_hasMultibyte ? 0x01 : 0x00);
|
||||
if (field_2_hasMultibyte) {
|
||||
StringUtil.putUnicodeLE(field_3_text, out);
|
||||
} else {
|
||||
StringUtil.putCompressedUnicode(field_3_text, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected final int getDataSize() {
|
||||
if (getTextLength() < 1) {
|
||||
return 0;
|
||||
}
|
||||
return 3 + getTextLength() * (field_2_hasMultibyte ? 2 : 1);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Common header/footer base class
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
abstract class HeaderFooterBase extends StandardRecord {
|
||||
private boolean field_2_hasMultibyte;
|
||||
private String field_3_text;
|
||||
|
||||
protected HeaderFooterBase(String text) {
|
||||
setText(text);
|
||||
}
|
||||
|
||||
protected HeaderFooterBase(RecordInputStream in) {
|
||||
if (in.remaining() > 0) {
|
||||
int field_1_footer_len = in.readShort();
|
||||
field_2_hasMultibyte = in.readByte() != 0x00;
|
||||
|
||||
if (field_2_hasMultibyte) {
|
||||
field_3_text = in.readUnicodeLEString(field_1_footer_len);
|
||||
} else {
|
||||
field_3_text = in.readCompressedUnicode(field_1_footer_len);
|
||||
}
|
||||
} else {
|
||||
// Note - this is unusual: when the text is empty string, the whole record is empty (just the 4 byte BIFF header)
|
||||
field_3_text = "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set the footer string
|
||||
*
|
||||
* @param text string to display
|
||||
*/
|
||||
public final void setText(String text) {
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text must not be null");
|
||||
}
|
||||
field_2_hasMultibyte = StringUtil.hasMultibyte(text);
|
||||
field_3_text = text;
|
||||
|
||||
// Check it'll fit into the space in the record
|
||||
if (field_2_hasMultibyte) {
|
||||
if (field_3_text.length() > 127) {
|
||||
throw new IllegalArgumentException(
|
||||
"Footer string too long (limit is 127 for unicode strings)");
|
||||
}
|
||||
} else {
|
||||
if (field_3_text.length() > 255) {
|
||||
throw new IllegalArgumentException(
|
||||
"Footer string too long (limit is 255 for non-unicode strings)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the length of the footer string
|
||||
*
|
||||
* @return length of the footer string
|
||||
*/
|
||||
private int getTextLength() {
|
||||
return field_3_text.length();
|
||||
}
|
||||
|
||||
public final String getText() {
|
||||
return field_3_text;
|
||||
}
|
||||
|
||||
public final void serialize(LittleEndianOutput out) {
|
||||
if (getTextLength() > 0) {
|
||||
out.writeShort(getTextLength());
|
||||
out.writeByte(field_2_hasMultibyte ? 0x01 : 0x00);
|
||||
if (field_2_hasMultibyte) {
|
||||
StringUtil.putUnicodeLE(field_3_text, out);
|
||||
} else {
|
||||
StringUtil.putCompressedUnicode(field_3_text, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected final int getDataSize() {
|
||||
if (getTextLength() < 1) {
|
||||
return 0;
|
||||
}
|
||||
return 3 + getTextLength() * (field_2_hasMultibyte ? 2 : 1);
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +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.record;
|
||||
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Subclasses of this class (the majority of BIFF records) are non-continuable. This allows for
|
||||
* some simplification of serialization logic
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class StandardRecord extends Record {
|
||||
protected abstract int getDataSize();
|
||||
public final int getRecordSize() {
|
||||
return 4 + getDataSize();
|
||||
}
|
||||
@Override
|
||||
public final int serialize(int offset, byte[] data) {
|
||||
int dataSize = getDataSize();
|
||||
int recSize = 4 + dataSize;
|
||||
LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(data, offset, recSize);
|
||||
out.writeShort(getSid());
|
||||
out.writeShort(dataSize);
|
||||
serialize(out);
|
||||
if (out.getWriteIndex() - offset != recSize) {
|
||||
throw new IllegalStateException("Error in serialization of (" + getClass().getName() + "): "
|
||||
+ "Incorrect number of bytes written - expected "
|
||||
+ recSize + " but got " + (out.getWriteIndex() - offset));
|
||||
}
|
||||
return recSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the data content of this BIFF record. The 'ushort sid' and 'ushort size' header fields
|
||||
* have already been written by the superclass.<br/>
|
||||
*
|
||||
* The subclass must write the exact number of bytes as reported by {@link org.apache.poi.hssf.record.Record#getRecordSize()}}
|
||||
*/
|
||||
protected abstract void serialize(LittleEndianOutput out);
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Subclasses of this class (the majority of BIFF records) are non-continuable. This allows for
|
||||
* some simplification of serialization logic
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class StandardRecord extends Record {
|
||||
protected abstract int getDataSize();
|
||||
public final int getRecordSize() {
|
||||
return 4 + getDataSize();
|
||||
}
|
||||
@Override
|
||||
public final int serialize(int offset, byte[] data) {
|
||||
int dataSize = getDataSize();
|
||||
int recSize = 4 + dataSize;
|
||||
LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(data, offset, recSize);
|
||||
out.writeShort(getSid());
|
||||
out.writeShort(dataSize);
|
||||
serialize(out);
|
||||
if (out.getWriteIndex() - offset != recSize) {
|
||||
throw new IllegalStateException("Error in serialization of (" + getClass().getName() + "): "
|
||||
+ "Incorrect number of bytes written - expected "
|
||||
+ recSize + " but got " + (out.getWriteIndex() - offset));
|
||||
}
|
||||
return recSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the data content of this BIFF record. The 'ushort sid' and 'ushort size' header fields
|
||||
* have already been written by the superclass.<br/>
|
||||
*
|
||||
* The subclass must write the exact number of bytes as reported by {@link org.apache.poi.hssf.record.Record#getRecordSize()}}
|
||||
*/
|
||||
protected abstract void serialize(LittleEndianOutput out);
|
||||
}
|
||||
|
@ -1,87 +1,87 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.aggregates;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.model.RecordStream;
|
||||
import org.apache.poi.hssf.record.BOFRecord;
|
||||
import org.apache.poi.hssf.record.EOFRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.hssf.record.RecordBase;
|
||||
import org.apache.poi.hssf.record.UnknownRecord;
|
||||
|
||||
/**
|
||||
* Manages the all the records associated with a chart sub-stream.<br/>
|
||||
* Includes the initial {@link BOFRecord} and final {@link EOFRecord}.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ChartSubstreamRecordAggregate extends RecordAggregate {
|
||||
|
||||
private final BOFRecord _bofRec;
|
||||
/**
|
||||
* All the records between BOF and EOF
|
||||
*/
|
||||
private final List<RecordBase> _recs;
|
||||
private PageSettingsBlock _psBlock;
|
||||
|
||||
public ChartSubstreamRecordAggregate(RecordStream rs) {
|
||||
_bofRec = (BOFRecord) rs.getNext();
|
||||
List<RecordBase> temp = new ArrayList<RecordBase>();
|
||||
while (rs.peekNextClass() != EOFRecord.class) {
|
||||
if (PageSettingsBlock.isComponentRecord(rs.peekNextSid())) {
|
||||
if (_psBlock != null) {
|
||||
if (rs.peekNextSid() == UnknownRecord.HEADER_FOOTER_089C) {
|
||||
// test samples: 45538_classic_Footer.xls, 45538_classic_Header.xls
|
||||
_psBlock.addLateHeaderFooter(rs.getNext());
|
||||
continue;
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Found more than one PageSettingsBlock in chart sub-stream");
|
||||
}
|
||||
_psBlock = new PageSettingsBlock(rs);
|
||||
temp.add(_psBlock);
|
||||
continue;
|
||||
}
|
||||
temp.add(rs.getNext());
|
||||
}
|
||||
_recs = temp;
|
||||
Record eof = rs.getNext(); // no need to save EOF in field
|
||||
if (!(eof instanceof EOFRecord)) {
|
||||
throw new IllegalStateException("Bad chart EOF");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitContainedRecords(RecordVisitor rv) {
|
||||
if (_recs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
rv.visitRecord(_bofRec);
|
||||
for (int i = 0; i < _recs.size(); i++) {
|
||||
RecordBase rb = _recs.get(i);
|
||||
if (rb instanceof RecordAggregate) {
|
||||
((RecordAggregate) rb).visitContainedRecords(rv);
|
||||
} else {
|
||||
rv.visitRecord((Record) rb);
|
||||
}
|
||||
}
|
||||
rv.visitRecord(EOFRecord.instance);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.aggregates;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.model.RecordStream;
|
||||
import org.apache.poi.hssf.record.BOFRecord;
|
||||
import org.apache.poi.hssf.record.EOFRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.hssf.record.RecordBase;
|
||||
import org.apache.poi.hssf.record.UnknownRecord;
|
||||
|
||||
/**
|
||||
* Manages the all the records associated with a chart sub-stream.<br/>
|
||||
* Includes the initial {@link BOFRecord} and final {@link EOFRecord}.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ChartSubstreamRecordAggregate extends RecordAggregate {
|
||||
|
||||
private final BOFRecord _bofRec;
|
||||
/**
|
||||
* All the records between BOF and EOF
|
||||
*/
|
||||
private final List<RecordBase> _recs;
|
||||
private PageSettingsBlock _psBlock;
|
||||
|
||||
public ChartSubstreamRecordAggregate(RecordStream rs) {
|
||||
_bofRec = (BOFRecord) rs.getNext();
|
||||
List<RecordBase> temp = new ArrayList<RecordBase>();
|
||||
while (rs.peekNextClass() != EOFRecord.class) {
|
||||
if (PageSettingsBlock.isComponentRecord(rs.peekNextSid())) {
|
||||
if (_psBlock != null) {
|
||||
if (rs.peekNextSid() == UnknownRecord.HEADER_FOOTER_089C) {
|
||||
// test samples: 45538_classic_Footer.xls, 45538_classic_Header.xls
|
||||
_psBlock.addLateHeaderFooter(rs.getNext());
|
||||
continue;
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Found more than one PageSettingsBlock in chart sub-stream");
|
||||
}
|
||||
_psBlock = new PageSettingsBlock(rs);
|
||||
temp.add(_psBlock);
|
||||
continue;
|
||||
}
|
||||
temp.add(rs.getNext());
|
||||
}
|
||||
_recs = temp;
|
||||
Record eof = rs.getNext(); // no need to save EOF in field
|
||||
if (!(eof instanceof EOFRecord)) {
|
||||
throw new IllegalStateException("Bad chart EOF");
|
||||
}
|
||||
}
|
||||
|
||||
public void visitContainedRecords(RecordVisitor rv) {
|
||||
if (_recs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
rv.visitRecord(_bofRec);
|
||||
for (int i = 0; i < _recs.size(); i++) {
|
||||
RecordBase rb = _recs.get(i);
|
||||
if (rb instanceof RecordAggregate) {
|
||||
((RecordAggregate) rb).visitContainedRecords(rv);
|
||||
} else {
|
||||
rv.visitRecord((Record) rb);
|
||||
}
|
||||
}
|
||||
rv.visitRecord(EOFRecord.instance);
|
||||
}
|
||||
}
|
||||
|
@ -1,70 +1,70 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.aggregates;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.model.RecordStream;
|
||||
import org.apache.poi.hssf.record.DVALRecord;
|
||||
import org.apache.poi.hssf.record.DVRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
|
||||
/**
|
||||
* Manages the DVALRecord and DVRecords for a single sheet<br/>
|
||||
* See OOO excelfileformat.pdf section 4.14
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class DataValidityTable extends RecordAggregate {
|
||||
|
||||
private final DVALRecord _headerRec;
|
||||
/**
|
||||
* The list of data validations for the current sheet.
|
||||
* Note - this may be empty (contrary to OOO documentation)
|
||||
*/
|
||||
private final List _validationList;
|
||||
|
||||
public DataValidityTable(RecordStream rs) {
|
||||
_headerRec = (DVALRecord) rs.getNext();
|
||||
List temp = new ArrayList();
|
||||
while (rs.peekNextClass() == DVRecord.class) {
|
||||
temp.add(rs.getNext());
|
||||
}
|
||||
_validationList = temp;
|
||||
}
|
||||
|
||||
public DataValidityTable() {
|
||||
_headerRec = new DVALRecord();
|
||||
_validationList = new ArrayList();
|
||||
}
|
||||
|
||||
public void visitContainedRecords(RecordVisitor rv) {
|
||||
if (_validationList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
rv.visitRecord(_headerRec);
|
||||
for (int i = 0; i < _validationList.size(); i++) {
|
||||
rv.visitRecord((Record) _validationList.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void addDataValidation(DVRecord dvRecord) {
|
||||
_validationList.add(dvRecord);
|
||||
_headerRec.setDVRecNo(_validationList.size());
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.aggregates;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.model.RecordStream;
|
||||
import org.apache.poi.hssf.record.DVALRecord;
|
||||
import org.apache.poi.hssf.record.DVRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
|
||||
/**
|
||||
* Manages the DVALRecord and DVRecords for a single sheet<br/>
|
||||
* See OOO excelfileformat.pdf section 4.14
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class DataValidityTable extends RecordAggregate {
|
||||
|
||||
private final DVALRecord _headerRec;
|
||||
/**
|
||||
* The list of data validations for the current sheet.
|
||||
* Note - this may be empty (contrary to OOO documentation)
|
||||
*/
|
||||
private final List _validationList;
|
||||
|
||||
public DataValidityTable(RecordStream rs) {
|
||||
_headerRec = (DVALRecord) rs.getNext();
|
||||
List temp = new ArrayList();
|
||||
while (rs.peekNextClass() == DVRecord.class) {
|
||||
temp.add(rs.getNext());
|
||||
}
|
||||
_validationList = temp;
|
||||
}
|
||||
|
||||
public DataValidityTable() {
|
||||
_headerRec = new DVALRecord();
|
||||
_validationList = new ArrayList();
|
||||
}
|
||||
|
||||
public void visitContainedRecords(RecordVisitor rv) {
|
||||
if (_validationList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
rv.visitRecord(_headerRec);
|
||||
for (int i = 0; i < _validationList.size(); i++) {
|
||||
rv.visitRecord((Record) _validationList.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void addDataValidation(DVRecord dvRecord) {
|
||||
_validationList.add(dvRecord);
|
||||
_headerRec.setDVRecNo(_validationList.size());
|
||||
}
|
||||
}
|
||||
|
@ -1,115 +1,115 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.aggregates;
|
||||
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.hssf.record.RecordBase;
|
||||
|
||||
/**
|
||||
* <tt>RecordAggregate</tt>s are groups of of BIFF <tt>Record</tt>s that are typically stored
|
||||
* together and/or updated together. Workbook / Sheet records are typically stored in a sequential
|
||||
* list, which does not provide much structure to coordinate updates.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class RecordAggregate extends RecordBase {
|
||||
|
||||
/**
|
||||
* Visit each of the atomic BIFF records contained in this {@link RecordAggregate} in the order
|
||||
* that they should be written to file. Implementors may or may not return the actual
|
||||
* {@link Record}s being used to manage POI's internal implementation. Callers should not
|
||||
* assume either way, and therefore only attempt to modify those {@link Record}s after cloning
|
||||
*/
|
||||
public abstract void visitContainedRecords(RecordVisitor rv);
|
||||
|
||||
public final int serialize(int offset, byte[] data) {
|
||||
SerializingRecordVisitor srv = new SerializingRecordVisitor(data, offset);
|
||||
visitContainedRecords(srv);
|
||||
return srv.countBytesWritten();
|
||||
}
|
||||
public int getRecordSize() {
|
||||
RecordSizingVisitor rsv = new RecordSizingVisitor();
|
||||
visitContainedRecords(rsv);
|
||||
return rsv.getTotalSize();
|
||||
}
|
||||
|
||||
public interface RecordVisitor {
|
||||
/**
|
||||
* Implementors may call non-mutating methods on Record r.
|
||||
* @param r must not be <code>null</code>
|
||||
*/
|
||||
void visitRecord(Record r);
|
||||
}
|
||||
|
||||
private static final class SerializingRecordVisitor implements RecordVisitor {
|
||||
|
||||
private final byte[] _data;
|
||||
private final int _startOffset;
|
||||
private int _countBytesWritten;
|
||||
|
||||
public SerializingRecordVisitor(byte[] data, int startOffset) {
|
||||
_data = data;
|
||||
_startOffset = startOffset;
|
||||
_countBytesWritten = 0;
|
||||
}
|
||||
public int countBytesWritten() {
|
||||
return _countBytesWritten;
|
||||
}
|
||||
public void visitRecord(Record r) {
|
||||
int currentOffset = _startOffset + _countBytesWritten;
|
||||
_countBytesWritten += r.serialize(currentOffset, _data);
|
||||
}
|
||||
}
|
||||
private static final class RecordSizingVisitor implements RecordVisitor {
|
||||
|
||||
private int _totalSize;
|
||||
|
||||
public RecordSizingVisitor() {
|
||||
_totalSize = 0;
|
||||
}
|
||||
public int getTotalSize() {
|
||||
return _totalSize;
|
||||
}
|
||||
public void visitRecord(Record r) {
|
||||
_totalSize += r.getRecordSize();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A wrapper for {@link RecordVisitor} which accumulates the sizes of all
|
||||
* records visited.
|
||||
*/
|
||||
public static final class PositionTrackingVisitor implements RecordVisitor {
|
||||
private final RecordVisitor _rv;
|
||||
private int _position;
|
||||
|
||||
public PositionTrackingVisitor(RecordVisitor rv, int initialPosition) {
|
||||
_rv = rv;
|
||||
_position = initialPosition;
|
||||
}
|
||||
public void visitRecord(Record r) {
|
||||
_position += r.getRecordSize();
|
||||
_rv.visitRecord(r);
|
||||
}
|
||||
public void setPosition(int position) {
|
||||
_position = position;
|
||||
}
|
||||
public int getPosition() {
|
||||
return _position;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.aggregates;
|
||||
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.hssf.record.RecordBase;
|
||||
|
||||
/**
|
||||
* <tt>RecordAggregate</tt>s are groups of of BIFF <tt>Record</tt>s that are typically stored
|
||||
* together and/or updated together. Workbook / Sheet records are typically stored in a sequential
|
||||
* list, which does not provide much structure to coordinate updates.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class RecordAggregate extends RecordBase {
|
||||
|
||||
/**
|
||||
* Visit each of the atomic BIFF records contained in this {@link RecordAggregate} in the order
|
||||
* that they should be written to file. Implementors may or may not return the actual
|
||||
* {@link Record}s being used to manage POI's internal implementation. Callers should not
|
||||
* assume either way, and therefore only attempt to modify those {@link Record}s after cloning
|
||||
*/
|
||||
public abstract void visitContainedRecords(RecordVisitor rv);
|
||||
|
||||
public final int serialize(int offset, byte[] data) {
|
||||
SerializingRecordVisitor srv = new SerializingRecordVisitor(data, offset);
|
||||
visitContainedRecords(srv);
|
||||
return srv.countBytesWritten();
|
||||
}
|
||||
public int getRecordSize() {
|
||||
RecordSizingVisitor rsv = new RecordSizingVisitor();
|
||||
visitContainedRecords(rsv);
|
||||
return rsv.getTotalSize();
|
||||
}
|
||||
|
||||
public interface RecordVisitor {
|
||||
/**
|
||||
* Implementors may call non-mutating methods on Record r.
|
||||
* @param r must not be <code>null</code>
|
||||
*/
|
||||
void visitRecord(Record r);
|
||||
}
|
||||
|
||||
private static final class SerializingRecordVisitor implements RecordVisitor {
|
||||
|
||||
private final byte[] _data;
|
||||
private final int _startOffset;
|
||||
private int _countBytesWritten;
|
||||
|
||||
public SerializingRecordVisitor(byte[] data, int startOffset) {
|
||||
_data = data;
|
||||
_startOffset = startOffset;
|
||||
_countBytesWritten = 0;
|
||||
}
|
||||
public int countBytesWritten() {
|
||||
return _countBytesWritten;
|
||||
}
|
||||
public void visitRecord(Record r) {
|
||||
int currentOffset = _startOffset + _countBytesWritten;
|
||||
_countBytesWritten += r.serialize(currentOffset, _data);
|
||||
}
|
||||
}
|
||||
private static final class RecordSizingVisitor implements RecordVisitor {
|
||||
|
||||
private int _totalSize;
|
||||
|
||||
public RecordSizingVisitor() {
|
||||
_totalSize = 0;
|
||||
}
|
||||
public int getTotalSize() {
|
||||
return _totalSize;
|
||||
}
|
||||
public void visitRecord(Record r) {
|
||||
_totalSize += r.getRecordSize();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A wrapper for {@link RecordVisitor} which accumulates the sizes of all
|
||||
* records visited.
|
||||
*/
|
||||
public static final class PositionTrackingVisitor implements RecordVisitor {
|
||||
private final RecordVisitor _rv;
|
||||
private int _position;
|
||||
|
||||
public PositionTrackingVisitor(RecordVisitor rv, int initialPosition) {
|
||||
_rv = rv;
|
||||
_position = initialPosition;
|
||||
}
|
||||
public void visitRecord(Record r) {
|
||||
_position += r.getRecordSize();
|
||||
_rv.visitRecord(r);
|
||||
}
|
||||
public void setPosition(int position) {
|
||||
_position = position;
|
||||
}
|
||||
public int getPosition() {
|
||||
return _position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +1,69 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.cont;
|
||||
|
||||
import org.apache.poi.hssf.record.ContinueRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Common superclass of all records that can produce {@link ContinueRecord}s while being serialized.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class ContinuableRecord extends Record {
|
||||
|
||||
protected ContinuableRecord() {
|
||||
// no fields to initialise
|
||||
}
|
||||
/**
|
||||
* Serializes this record's content to the supplied data output.<br/>
|
||||
* The standard BIFF header (ushort sid, ushort size) has been handled by the superclass, so
|
||||
* only BIFF data should be written by this method. Simple data types can be written with the
|
||||
* standard {@link LittleEndianOutput} methods. Methods from {@link ContinuableRecordOutput}
|
||||
* can be used to serialize strings (with {@link ContinueRecord}s being written as required).
|
||||
* If necessary, implementors can explicitly start {@link ContinueRecord}s (regardless of the
|
||||
* amount of remaining space).
|
||||
*
|
||||
* @param out a data output stream
|
||||
*/
|
||||
protected abstract void serialize(ContinuableRecordOutput out);
|
||||
|
||||
|
||||
/**
|
||||
* @return the total length of the encoded record(s)
|
||||
* (Note - if any {@link ContinueRecord} is required, this result includes the
|
||||
* size of those too)
|
||||
*/
|
||||
public final int getRecordSize() {
|
||||
ContinuableRecordOutput out = ContinuableRecordOutput.createForCountingOnly();
|
||||
serialize(out);
|
||||
out.terminate();
|
||||
return out.getTotalSize();
|
||||
}
|
||||
|
||||
public final int serialize(int offset, byte[] data) {
|
||||
|
||||
LittleEndianOutput leo = new LittleEndianByteArrayOutputStream(data, offset);
|
||||
ContinuableRecordOutput out = new ContinuableRecordOutput(leo, getSid());
|
||||
serialize(out);
|
||||
out.terminate();
|
||||
return out.getTotalSize();
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.cont;
|
||||
|
||||
import org.apache.poi.hssf.record.ContinueRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Common superclass of all records that can produce {@link ContinueRecord}s while being serialized.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class ContinuableRecord extends Record {
|
||||
|
||||
protected ContinuableRecord() {
|
||||
// no fields to initialise
|
||||
}
|
||||
/**
|
||||
* Serializes this record's content to the supplied data output.<br/>
|
||||
* The standard BIFF header (ushort sid, ushort size) has been handled by the superclass, so
|
||||
* only BIFF data should be written by this method. Simple data types can be written with the
|
||||
* standard {@link LittleEndianOutput} methods. Methods from {@link ContinuableRecordOutput}
|
||||
* can be used to serialize strings (with {@link ContinueRecord}s being written as required).
|
||||
* If necessary, implementors can explicitly start {@link ContinueRecord}s (regardless of the
|
||||
* amount of remaining space).
|
||||
*
|
||||
* @param out a data output stream
|
||||
*/
|
||||
protected abstract void serialize(ContinuableRecordOutput out);
|
||||
|
||||
|
||||
/**
|
||||
* @return the total length of the encoded record(s)
|
||||
* (Note - if any {@link ContinueRecord} is required, this result includes the
|
||||
* size of those too)
|
||||
*/
|
||||
public final int getRecordSize() {
|
||||
ContinuableRecordOutput out = ContinuableRecordOutput.createForCountingOnly();
|
||||
serialize(out);
|
||||
out.terminate();
|
||||
return out.getTotalSize();
|
||||
}
|
||||
|
||||
public final int serialize(int offset, byte[] data) {
|
||||
|
||||
LittleEndianOutput leo = new LittleEndianByteArrayOutputStream(data, offset);
|
||||
ContinuableRecordOutput out = new ContinuableRecordOutput(leo, getSid());
|
||||
serialize(out);
|
||||
out.terminate();
|
||||
return out.getTotalSize();
|
||||
}
|
||||
}
|
||||
|
@ -1,257 +1,257 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.cont;
|
||||
|
||||
import org.apache.poi.hssf.record.ContinueRecord;
|
||||
import org.apache.poi.util.DelayableLittleEndianOutput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
/**
|
||||
* An augmented {@link LittleEndianOutput} used for serialization of {@link ContinuableRecord}s.
|
||||
* This class keeps track of how much remaining space is available in the current BIFF record and
|
||||
* can start new {@link ContinueRecord}s as required.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ContinuableRecordOutput implements LittleEndianOutput {
|
||||
|
||||
private final LittleEndianOutput _out;
|
||||
private UnknownLengthRecordOutput _ulrOutput;
|
||||
private int _totalPreviousRecordsSize;
|
||||
|
||||
ContinuableRecordOutput(LittleEndianOutput out, int sid) {
|
||||
_ulrOutput = new UnknownLengthRecordOutput(out, sid);
|
||||
_out = out;
|
||||
_totalPreviousRecordsSize = 0;
|
||||
}
|
||||
|
||||
public static ContinuableRecordOutput createForCountingOnly() {
|
||||
return new ContinuableRecordOutput(NOPOutput, -777); // fake sid
|
||||
}
|
||||
|
||||
/**
|
||||
* @return total number of bytes written so far (including all BIFF headers)
|
||||
*/
|
||||
public int getTotalSize() {
|
||||
return _totalPreviousRecordsSize + _ulrOutput.getTotalSize();
|
||||
}
|
||||
/**
|
||||
* Terminates the last record (also updates its 'ushort size' field)
|
||||
*/
|
||||
void terminate() {
|
||||
_ulrOutput.terminate();
|
||||
}
|
||||
/**
|
||||
* @return number of remaining bytes of space in current record
|
||||
*/
|
||||
public int getAvailableSpace() {
|
||||
return _ulrOutput.getAvailableSpace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the current record and starts a new {@link ContinueRecord} (regardless
|
||||
* of how much space is still available in the current record).
|
||||
*/
|
||||
public void writeContinue() {
|
||||
_ulrOutput.terminate();
|
||||
_totalPreviousRecordsSize += _ulrOutput.getTotalSize();
|
||||
_ulrOutput = new UnknownLengthRecordOutput(_out, ContinueRecord.sid);
|
||||
}
|
||||
public void writeContinueIfRequired(int requiredContinuousSize) {
|
||||
if (_ulrOutput.getAvailableSpace() < requiredContinuousSize) {
|
||||
writeContinue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the 'optionFlags' byte and encoded character data of a unicode string. This includes:
|
||||
* <ul>
|
||||
* <li>byte optionFlags</li>
|
||||
* <li>encoded character data (in "ISO-8859-1" or "UTF-16LE" encoding)</li>
|
||||
* </ul>
|
||||
*
|
||||
* Notes:
|
||||
* <ul>
|
||||
* <li>The value of the 'is16bitEncoded' flag is determined by the actual character data
|
||||
* of <tt>text</tt></li>
|
||||
* <li>The string options flag is never separated (by a {@link ContinueRecord}) from the
|
||||
* first chunk of character data it refers to.</li>
|
||||
* <li>The 'ushort length' field is assumed to have been explicitly written earlier. Hence,
|
||||
* there may be an intervening {@link ContinueRecord}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void writeStringData(String text) {
|
||||
boolean is16bitEncoded = StringUtil.hasMultibyte(text);
|
||||
// calculate total size of the header and first encoded char
|
||||
int keepTogetherSize = 1 + 1; // ushort len, at least one character byte
|
||||
int optionFlags = 0x00;
|
||||
if (is16bitEncoded) {
|
||||
optionFlags |= 0x01;
|
||||
keepTogetherSize += 1; // one extra byte for first char
|
||||
}
|
||||
writeContinueIfRequired(keepTogetherSize);
|
||||
writeByte(optionFlags);
|
||||
writeCharacterData(text, is16bitEncoded);
|
||||
}
|
||||
/**
|
||||
* Writes a unicode string complete with header and character data. This includes:
|
||||
* <ul>
|
||||
* <li>ushort length</li>
|
||||
* <li>byte optionFlags</li>
|
||||
* <li>ushort numberOfRichTextRuns (optional)</li>
|
||||
* <li>ushort extendedDataSize (optional)</li>
|
||||
* <li>encoded character data (in "ISO-8859-1" or "UTF-16LE" encoding)</li>
|
||||
* </ul>
|
||||
*
|
||||
* The following bits of the 'optionFlags' byte will be set as appropriate:
|
||||
* <table border='1'>
|
||||
* <tr><th>Mask</th><th>Description</th></tr>
|
||||
* <tr><td>0x01</td><td>is16bitEncoded</td></tr>
|
||||
* <tr><td>0x04</td><td>hasExtendedData</td></tr>
|
||||
* <tr><td>0x08</td><td>isRichText</td></tr>
|
||||
* </table>
|
||||
* Notes:
|
||||
* <ul>
|
||||
* <li>The value of the 'is16bitEncoded' flag is determined by the actual character data
|
||||
* of <tt>text</tt></li>
|
||||
* <li>The string header fields are never separated (by a {@link ContinueRecord}) from the
|
||||
* first chunk of character data (i.e. the first character is always encoded in the same
|
||||
* record as the string header).</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void writeString(String text, int numberOfRichTextRuns, int extendedDataSize) {
|
||||
boolean is16bitEncoded = StringUtil.hasMultibyte(text);
|
||||
// calculate total size of the header and first encoded char
|
||||
int keepTogetherSize = 2 + 1 + 1; // ushort len, byte optionFlags, at least one character byte
|
||||
int optionFlags = 0x00;
|
||||
if (is16bitEncoded) {
|
||||
optionFlags |= 0x01;
|
||||
keepTogetherSize += 1; // one extra byte for first char
|
||||
}
|
||||
if (numberOfRichTextRuns > 0) {
|
||||
optionFlags |= 0x08;
|
||||
keepTogetherSize += 2;
|
||||
}
|
||||
if (extendedDataSize > 0) {
|
||||
optionFlags |= 0x04;
|
||||
keepTogetherSize += 4;
|
||||
}
|
||||
writeContinueIfRequired(keepTogetherSize);
|
||||
writeShort(text.length());
|
||||
writeByte(optionFlags);
|
||||
if (numberOfRichTextRuns > 0) {
|
||||
writeShort(numberOfRichTextRuns);
|
||||
}
|
||||
if (extendedDataSize > 0) {
|
||||
writeInt(extendedDataSize);
|
||||
}
|
||||
writeCharacterData(text, is16bitEncoded);
|
||||
}
|
||||
|
||||
|
||||
private void writeCharacterData(String text, boolean is16bitEncoded) {
|
||||
int nChars = text.length();
|
||||
int i=0;
|
||||
if (is16bitEncoded) {
|
||||
while(true) {
|
||||
int nWritableChars = Math.min(nChars-i, _ulrOutput.getAvailableSpace() / 2);
|
||||
for ( ; nWritableChars > 0; nWritableChars--) {
|
||||
_ulrOutput.writeShort(text.charAt(i++));
|
||||
}
|
||||
if (i >= nChars) {
|
||||
break;
|
||||
}
|
||||
writeContinue();
|
||||
writeByte(0x01);
|
||||
}
|
||||
} else {
|
||||
while(true) {
|
||||
int nWritableChars = Math.min(nChars-i, _ulrOutput.getAvailableSpace() / 1);
|
||||
for ( ; nWritableChars > 0; nWritableChars--) {
|
||||
_ulrOutput.writeByte(text.charAt(i++));
|
||||
}
|
||||
if (i >= nChars) {
|
||||
break;
|
||||
}
|
||||
writeContinue();
|
||||
writeByte(0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(byte[] b) {
|
||||
writeContinueIfRequired(b.length);
|
||||
_ulrOutput.write(b);
|
||||
}
|
||||
public void write(byte[] b, int offset, int len) {
|
||||
writeContinueIfRequired(len);
|
||||
_ulrOutput.write(b, offset, len);
|
||||
}
|
||||
public void writeByte(int v) {
|
||||
writeContinueIfRequired(1);
|
||||
_ulrOutput.writeByte(v);
|
||||
}
|
||||
public void writeDouble(double v) {
|
||||
writeContinueIfRequired(8);
|
||||
_ulrOutput.writeDouble(v);
|
||||
}
|
||||
public void writeInt(int v) {
|
||||
writeContinueIfRequired(4);
|
||||
_ulrOutput.writeInt(v);
|
||||
}
|
||||
public void writeLong(long v) {
|
||||
writeContinueIfRequired(8);
|
||||
_ulrOutput.writeLong(v);
|
||||
}
|
||||
public void writeShort(int v) {
|
||||
writeContinueIfRequired(2);
|
||||
_ulrOutput.writeShort(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows optimised usage of {@link ContinuableRecordOutput} for sizing purposes only.
|
||||
*/
|
||||
private static final LittleEndianOutput NOPOutput = new DelayableLittleEndianOutput() {
|
||||
|
||||
public LittleEndianOutput createDelayedOutput(int size) {
|
||||
return this;
|
||||
}
|
||||
public void write(byte[] b) {
|
||||
// does nothing
|
||||
}
|
||||
public void write(byte[] b, int offset, int len) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeByte(int v) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeDouble(double v) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeInt(int v) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeLong(long v) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeShort(int v) {
|
||||
// does nothing
|
||||
}
|
||||
};
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.cont;
|
||||
|
||||
import org.apache.poi.hssf.record.ContinueRecord;
|
||||
import org.apache.poi.util.DelayableLittleEndianOutput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
/**
|
||||
* An augmented {@link LittleEndianOutput} used for serialization of {@link ContinuableRecord}s.
|
||||
* This class keeps track of how much remaining space is available in the current BIFF record and
|
||||
* can start new {@link ContinueRecord}s as required.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ContinuableRecordOutput implements LittleEndianOutput {
|
||||
|
||||
private final LittleEndianOutput _out;
|
||||
private UnknownLengthRecordOutput _ulrOutput;
|
||||
private int _totalPreviousRecordsSize;
|
||||
|
||||
ContinuableRecordOutput(LittleEndianOutput out, int sid) {
|
||||
_ulrOutput = new UnknownLengthRecordOutput(out, sid);
|
||||
_out = out;
|
||||
_totalPreviousRecordsSize = 0;
|
||||
}
|
||||
|
||||
public static ContinuableRecordOutput createForCountingOnly() {
|
||||
return new ContinuableRecordOutput(NOPOutput, -777); // fake sid
|
||||
}
|
||||
|
||||
/**
|
||||
* @return total number of bytes written so far (including all BIFF headers)
|
||||
*/
|
||||
public int getTotalSize() {
|
||||
return _totalPreviousRecordsSize + _ulrOutput.getTotalSize();
|
||||
}
|
||||
/**
|
||||
* Terminates the last record (also updates its 'ushort size' field)
|
||||
*/
|
||||
void terminate() {
|
||||
_ulrOutput.terminate();
|
||||
}
|
||||
/**
|
||||
* @return number of remaining bytes of space in current record
|
||||
*/
|
||||
public int getAvailableSpace() {
|
||||
return _ulrOutput.getAvailableSpace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the current record and starts a new {@link ContinueRecord} (regardless
|
||||
* of how much space is still available in the current record).
|
||||
*/
|
||||
public void writeContinue() {
|
||||
_ulrOutput.terminate();
|
||||
_totalPreviousRecordsSize += _ulrOutput.getTotalSize();
|
||||
_ulrOutput = new UnknownLengthRecordOutput(_out, ContinueRecord.sid);
|
||||
}
|
||||
public void writeContinueIfRequired(int requiredContinuousSize) {
|
||||
if (_ulrOutput.getAvailableSpace() < requiredContinuousSize) {
|
||||
writeContinue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the 'optionFlags' byte and encoded character data of a unicode string. This includes:
|
||||
* <ul>
|
||||
* <li>byte optionFlags</li>
|
||||
* <li>encoded character data (in "ISO-8859-1" or "UTF-16LE" encoding)</li>
|
||||
* </ul>
|
||||
*
|
||||
* Notes:
|
||||
* <ul>
|
||||
* <li>The value of the 'is16bitEncoded' flag is determined by the actual character data
|
||||
* of <tt>text</tt></li>
|
||||
* <li>The string options flag is never separated (by a {@link ContinueRecord}) from the
|
||||
* first chunk of character data it refers to.</li>
|
||||
* <li>The 'ushort length' field is assumed to have been explicitly written earlier. Hence,
|
||||
* there may be an intervening {@link ContinueRecord}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void writeStringData(String text) {
|
||||
boolean is16bitEncoded = StringUtil.hasMultibyte(text);
|
||||
// calculate total size of the header and first encoded char
|
||||
int keepTogetherSize = 1 + 1; // ushort len, at least one character byte
|
||||
int optionFlags = 0x00;
|
||||
if (is16bitEncoded) {
|
||||
optionFlags |= 0x01;
|
||||
keepTogetherSize += 1; // one extra byte for first char
|
||||
}
|
||||
writeContinueIfRequired(keepTogetherSize);
|
||||
writeByte(optionFlags);
|
||||
writeCharacterData(text, is16bitEncoded);
|
||||
}
|
||||
/**
|
||||
* Writes a unicode string complete with header and character data. This includes:
|
||||
* <ul>
|
||||
* <li>ushort length</li>
|
||||
* <li>byte optionFlags</li>
|
||||
* <li>ushort numberOfRichTextRuns (optional)</li>
|
||||
* <li>ushort extendedDataSize (optional)</li>
|
||||
* <li>encoded character data (in "ISO-8859-1" or "UTF-16LE" encoding)</li>
|
||||
* </ul>
|
||||
*
|
||||
* The following bits of the 'optionFlags' byte will be set as appropriate:
|
||||
* <table border='1'>
|
||||
* <tr><th>Mask</th><th>Description</th></tr>
|
||||
* <tr><td>0x01</td><td>is16bitEncoded</td></tr>
|
||||
* <tr><td>0x04</td><td>hasExtendedData</td></tr>
|
||||
* <tr><td>0x08</td><td>isRichText</td></tr>
|
||||
* </table>
|
||||
* Notes:
|
||||
* <ul>
|
||||
* <li>The value of the 'is16bitEncoded' flag is determined by the actual character data
|
||||
* of <tt>text</tt></li>
|
||||
* <li>The string header fields are never separated (by a {@link ContinueRecord}) from the
|
||||
* first chunk of character data (i.e. the first character is always encoded in the same
|
||||
* record as the string header).</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void writeString(String text, int numberOfRichTextRuns, int extendedDataSize) {
|
||||
boolean is16bitEncoded = StringUtil.hasMultibyte(text);
|
||||
// calculate total size of the header and first encoded char
|
||||
int keepTogetherSize = 2 + 1 + 1; // ushort len, byte optionFlags, at least one character byte
|
||||
int optionFlags = 0x00;
|
||||
if (is16bitEncoded) {
|
||||
optionFlags |= 0x01;
|
||||
keepTogetherSize += 1; // one extra byte for first char
|
||||
}
|
||||
if (numberOfRichTextRuns > 0) {
|
||||
optionFlags |= 0x08;
|
||||
keepTogetherSize += 2;
|
||||
}
|
||||
if (extendedDataSize > 0) {
|
||||
optionFlags |= 0x04;
|
||||
keepTogetherSize += 4;
|
||||
}
|
||||
writeContinueIfRequired(keepTogetherSize);
|
||||
writeShort(text.length());
|
||||
writeByte(optionFlags);
|
||||
if (numberOfRichTextRuns > 0) {
|
||||
writeShort(numberOfRichTextRuns);
|
||||
}
|
||||
if (extendedDataSize > 0) {
|
||||
writeInt(extendedDataSize);
|
||||
}
|
||||
writeCharacterData(text, is16bitEncoded);
|
||||
}
|
||||
|
||||
|
||||
private void writeCharacterData(String text, boolean is16bitEncoded) {
|
||||
int nChars = text.length();
|
||||
int i=0;
|
||||
if (is16bitEncoded) {
|
||||
while(true) {
|
||||
int nWritableChars = Math.min(nChars-i, _ulrOutput.getAvailableSpace() / 2);
|
||||
for ( ; nWritableChars > 0; nWritableChars--) {
|
||||
_ulrOutput.writeShort(text.charAt(i++));
|
||||
}
|
||||
if (i >= nChars) {
|
||||
break;
|
||||
}
|
||||
writeContinue();
|
||||
writeByte(0x01);
|
||||
}
|
||||
} else {
|
||||
while(true) {
|
||||
int nWritableChars = Math.min(nChars-i, _ulrOutput.getAvailableSpace() / 1);
|
||||
for ( ; nWritableChars > 0; nWritableChars--) {
|
||||
_ulrOutput.writeByte(text.charAt(i++));
|
||||
}
|
||||
if (i >= nChars) {
|
||||
break;
|
||||
}
|
||||
writeContinue();
|
||||
writeByte(0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(byte[] b) {
|
||||
writeContinueIfRequired(b.length);
|
||||
_ulrOutput.write(b);
|
||||
}
|
||||
public void write(byte[] b, int offset, int len) {
|
||||
writeContinueIfRequired(len);
|
||||
_ulrOutput.write(b, offset, len);
|
||||
}
|
||||
public void writeByte(int v) {
|
||||
writeContinueIfRequired(1);
|
||||
_ulrOutput.writeByte(v);
|
||||
}
|
||||
public void writeDouble(double v) {
|
||||
writeContinueIfRequired(8);
|
||||
_ulrOutput.writeDouble(v);
|
||||
}
|
||||
public void writeInt(int v) {
|
||||
writeContinueIfRequired(4);
|
||||
_ulrOutput.writeInt(v);
|
||||
}
|
||||
public void writeLong(long v) {
|
||||
writeContinueIfRequired(8);
|
||||
_ulrOutput.writeLong(v);
|
||||
}
|
||||
public void writeShort(int v) {
|
||||
writeContinueIfRequired(2);
|
||||
_ulrOutput.writeShort(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows optimised usage of {@link ContinuableRecordOutput} for sizing purposes only.
|
||||
*/
|
||||
private static final LittleEndianOutput NOPOutput = new DelayableLittleEndianOutput() {
|
||||
|
||||
public LittleEndianOutput createDelayedOutput(int size) {
|
||||
return this;
|
||||
}
|
||||
public void write(byte[] b) {
|
||||
// does nothing
|
||||
}
|
||||
public void write(byte[] b, int offset, int len) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeByte(int v) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeDouble(double v) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeInt(int v) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeLong(long v) {
|
||||
// does nothing
|
||||
}
|
||||
public void writeShort(int v) {
|
||||
// does nothing
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,114 +1,114 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.cont;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.util.DelayableLittleEndianOutput;
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
/**
|
||||
* Allows the writing of BIFF records when the 'ushort size' header field is not known in advance.
|
||||
* When the client is finished writing data, it calls {@link #terminate()}, at which point this
|
||||
* class updates the 'ushort size' with its final value.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class UnknownLengthRecordOutput implements LittleEndianOutput {
|
||||
private static final int MAX_DATA_SIZE = RecordInputStream.MAX_RECORD_DATA_SIZE;
|
||||
|
||||
private final LittleEndianOutput _originalOut;
|
||||
/** for writing the 'ushort size' field once its value is known */
|
||||
private final LittleEndianOutput _dataSizeOutput;
|
||||
private final byte[] _byteBuffer;
|
||||
private LittleEndianOutput _out;
|
||||
private int _size;
|
||||
|
||||
public UnknownLengthRecordOutput(LittleEndianOutput out, int sid) {
|
||||
_originalOut = out;
|
||||
out.writeShort(sid);
|
||||
if (out instanceof DelayableLittleEndianOutput) {
|
||||
// optimisation
|
||||
DelayableLittleEndianOutput dleo = (DelayableLittleEndianOutput) out;
|
||||
_dataSizeOutput = dleo.createDelayedOutput(2);
|
||||
_byteBuffer = null;
|
||||
_out = out;
|
||||
} else {
|
||||
// otherwise temporarily write all subsequent data to a buffer
|
||||
_dataSizeOutput = out;
|
||||
_byteBuffer = new byte[RecordInputStream.MAX_RECORD_DATA_SIZE];
|
||||
_out = new LittleEndianByteArrayOutputStream(_byteBuffer, 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* includes 4 byte header
|
||||
*/
|
||||
public int getTotalSize() {
|
||||
return 4 + _size;
|
||||
}
|
||||
public int getAvailableSpace() {
|
||||
if (_out == null) {
|
||||
throw new IllegalStateException("Record already terminated");
|
||||
}
|
||||
return MAX_DATA_SIZE - _size;
|
||||
}
|
||||
/**
|
||||
* Finishes writing the current record and updates 'ushort size' field.<br/>
|
||||
* After this method is called, only {@link #getTotalSize()} may be called.
|
||||
*/
|
||||
public void terminate() {
|
||||
if (_out == null) {
|
||||
throw new IllegalStateException("Record already terminated");
|
||||
}
|
||||
_dataSizeOutput.writeShort(_size);
|
||||
if (_byteBuffer != null) {
|
||||
_originalOut.write(_byteBuffer, 0, _size);
|
||||
_out = null;
|
||||
return;
|
||||
}
|
||||
_out = null;
|
||||
}
|
||||
|
||||
public void write(byte[] b) {
|
||||
_out.write(b);
|
||||
_size += b.length;
|
||||
}
|
||||
public void write(byte[] b, int offset, int len) {
|
||||
_out.write(b, offset, len);
|
||||
_size += len;
|
||||
}
|
||||
public void writeByte(int v) {
|
||||
_out.writeByte(v);
|
||||
_size += 1;
|
||||
}
|
||||
public void writeDouble(double v) {
|
||||
_out.writeDouble(v);
|
||||
_size += 8;
|
||||
}
|
||||
public void writeInt(int v) {
|
||||
_out.writeInt(v);
|
||||
_size += 4;
|
||||
}
|
||||
public void writeLong(long v) {
|
||||
_out.writeLong(v);
|
||||
_size += 8;
|
||||
}
|
||||
public void writeShort(int v) {
|
||||
_out.writeShort(v);
|
||||
_size += 2;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.cont;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.util.DelayableLittleEndianOutput;
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
/**
|
||||
* Allows the writing of BIFF records when the 'ushort size' header field is not known in advance.
|
||||
* When the client is finished writing data, it calls {@link #terminate()}, at which point this
|
||||
* class updates the 'ushort size' with its final value.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class UnknownLengthRecordOutput implements LittleEndianOutput {
|
||||
private static final int MAX_DATA_SIZE = RecordInputStream.MAX_RECORD_DATA_SIZE;
|
||||
|
||||
private final LittleEndianOutput _originalOut;
|
||||
/** for writing the 'ushort size' field once its value is known */
|
||||
private final LittleEndianOutput _dataSizeOutput;
|
||||
private final byte[] _byteBuffer;
|
||||
private LittleEndianOutput _out;
|
||||
private int _size;
|
||||
|
||||
public UnknownLengthRecordOutput(LittleEndianOutput out, int sid) {
|
||||
_originalOut = out;
|
||||
out.writeShort(sid);
|
||||
if (out instanceof DelayableLittleEndianOutput) {
|
||||
// optimisation
|
||||
DelayableLittleEndianOutput dleo = (DelayableLittleEndianOutput) out;
|
||||
_dataSizeOutput = dleo.createDelayedOutput(2);
|
||||
_byteBuffer = null;
|
||||
_out = out;
|
||||
} else {
|
||||
// otherwise temporarily write all subsequent data to a buffer
|
||||
_dataSizeOutput = out;
|
||||
_byteBuffer = new byte[RecordInputStream.MAX_RECORD_DATA_SIZE];
|
||||
_out = new LittleEndianByteArrayOutputStream(_byteBuffer, 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* includes 4 byte header
|
||||
*/
|
||||
public int getTotalSize() {
|
||||
return 4 + _size;
|
||||
}
|
||||
public int getAvailableSpace() {
|
||||
if (_out == null) {
|
||||
throw new IllegalStateException("Record already terminated");
|
||||
}
|
||||
return MAX_DATA_SIZE - _size;
|
||||
}
|
||||
/**
|
||||
* Finishes writing the current record and updates 'ushort size' field.<br/>
|
||||
* After this method is called, only {@link #getTotalSize()} may be called.
|
||||
*/
|
||||
public void terminate() {
|
||||
if (_out == null) {
|
||||
throw new IllegalStateException("Record already terminated");
|
||||
}
|
||||
_dataSizeOutput.writeShort(_size);
|
||||
if (_byteBuffer != null) {
|
||||
_originalOut.write(_byteBuffer, 0, _size);
|
||||
_out = null;
|
||||
return;
|
||||
}
|
||||
_out = null;
|
||||
}
|
||||
|
||||
public void write(byte[] b) {
|
||||
_out.write(b);
|
||||
_size += b.length;
|
||||
}
|
||||
public void write(byte[] b, int offset, int len) {
|
||||
_out.write(b, offset, len);
|
||||
_size += len;
|
||||
}
|
||||
public void writeByte(int v) {
|
||||
_out.writeByte(v);
|
||||
_size += 1;
|
||||
}
|
||||
public void writeDouble(double v) {
|
||||
_out.writeDouble(v);
|
||||
_size += 8;
|
||||
}
|
||||
public void writeInt(int v) {
|
||||
_out.writeInt(v);
|
||||
_size += 4;
|
||||
}
|
||||
public void writeLong(long v) {
|
||||
_out.writeLong(v);
|
||||
_size += 8;
|
||||
}
|
||||
public void writeShort(int v) {
|
||||
_out.writeShort(v);
|
||||
_size += 2;
|
||||
}
|
||||
}
|
||||
|
@ -1,64 +1,64 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.ss.util.AreaReference;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Common superclass of 2-D area refs
|
||||
*/
|
||||
public abstract class Area2DPtgBase extends AreaPtgBase {
|
||||
private final static int SIZE = 9;
|
||||
|
||||
protected Area2DPtgBase(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
|
||||
super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
|
||||
}
|
||||
protected Area2DPtgBase(AreaReference ar) {
|
||||
super(ar);
|
||||
}
|
||||
|
||||
protected Area2DPtgBase(LittleEndianInput in) {
|
||||
readCoordinates(in);
|
||||
}
|
||||
|
||||
protected abstract byte getSid();
|
||||
|
||||
public final void write(LittleEndianOutput out) {
|
||||
out.writeByte(getSid() + getPtgClass());
|
||||
writeCoordinates(out);
|
||||
}
|
||||
|
||||
public final int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public final String toFormulaString() {
|
||||
return formatReferenceAsString();
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName());
|
||||
sb.append(" [");
|
||||
sb.append(formatReferenceAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.ss.util.AreaReference;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Common superclass of 2-D area refs
|
||||
*/
|
||||
public abstract class Area2DPtgBase extends AreaPtgBase {
|
||||
private final static int SIZE = 9;
|
||||
|
||||
protected Area2DPtgBase(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
|
||||
super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
|
||||
}
|
||||
protected Area2DPtgBase(AreaReference ar) {
|
||||
super(ar);
|
||||
}
|
||||
|
||||
protected Area2DPtgBase(LittleEndianInput in) {
|
||||
readCoordinates(in);
|
||||
}
|
||||
|
||||
protected abstract byte getSid();
|
||||
|
||||
public final void write(LittleEndianOutput out) {
|
||||
out.writeByte(getSid() + getPtgClass());
|
||||
writeCoordinates(out);
|
||||
}
|
||||
|
||||
public final int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public final String toFormulaString() {
|
||||
return formatReferenceAsString();
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName());
|
||||
sb.append(" [");
|
||||
sb.append(formatReferenceAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +1,54 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
|
||||
/**
|
||||
* ReferencePtg - handles references (such as A1, A2, IA4)
|
||||
* @author Andrew C. Oliver (acoliver@apache.org)
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class RefPtg extends Ref2DPtgBase {
|
||||
public final static byte sid = 0x24;
|
||||
|
||||
/**
|
||||
* Takes in a String representation of a cell reference and fills out the
|
||||
* numeric fields.
|
||||
*/
|
||||
public RefPtg(String cellref) {
|
||||
super(new CellReference(cellref));
|
||||
}
|
||||
|
||||
public RefPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
|
||||
super(row, column, isRowRelative, isColumnRelative);
|
||||
}
|
||||
|
||||
public RefPtg(LittleEndianInput in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public RefPtg(CellReference cr) {
|
||||
super(cr);
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
|
||||
/**
|
||||
* ReferencePtg - handles references (such as A1, A2, IA4)
|
||||
* @author Andrew C. Oliver (acoliver@apache.org)
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public final class RefPtg extends Ref2DPtgBase {
|
||||
public final static byte sid = 0x24;
|
||||
|
||||
/**
|
||||
* Takes in a String representation of a cell reference and fills out the
|
||||
* numeric fields.
|
||||
*/
|
||||
public RefPtg(String cellref) {
|
||||
super(new CellReference(cellref));
|
||||
}
|
||||
|
||||
public RefPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
|
||||
super(row, column, isRowRelative, isColumnRelative);
|
||||
}
|
||||
|
||||
public RefPtg(LittleEndianInput in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public RefPtg(CellReference cr) {
|
||||
super(cr);
|
||||
}
|
||||
|
||||
protected byte getSid() {
|
||||
return sid;
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +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.record.formula;
|
||||
|
||||
|
||||
/**
|
||||
* @author Josh Micich
|
||||
*/
|
||||
abstract class ScalarConstantPtg extends Ptg {
|
||||
public boolean isBaseToken() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public final byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append(toFormulaString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
|
||||
/**
|
||||
* @author Josh Micich
|
||||
*/
|
||||
abstract class ScalarConstantPtg extends Ptg {
|
||||
public boolean isBaseToken() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public final byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append(toFormulaString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +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.record.formula.eval;
|
||||
|
||||
/**
|
||||
* Common base class for implementors of {@link RefEval}
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class RefEvalBase implements RefEval {
|
||||
|
||||
private final int _rowIndex;
|
||||
private final int _columnIndex;
|
||||
|
||||
protected RefEvalBase(int rowIndex, int columnIndex) {
|
||||
_rowIndex = rowIndex;
|
||||
_columnIndex = columnIndex;
|
||||
}
|
||||
public final int getRow() {
|
||||
return _rowIndex;
|
||||
}
|
||||
public final int getColumn() {
|
||||
return _columnIndex;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula.eval;
|
||||
|
||||
/**
|
||||
* Common base class for implementors of {@link RefEval}
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class RefEvalBase implements RefEval {
|
||||
|
||||
private final int _rowIndex;
|
||||
private final int _columnIndex;
|
||||
|
||||
protected RefEvalBase(int rowIndex, int columnIndex) {
|
||||
_rowIndex = rowIndex;
|
||||
_columnIndex = columnIndex;
|
||||
}
|
||||
public final int getRow() {
|
||||
return _rowIndex;
|
||||
}
|
||||
public final int getColumn() {
|
||||
return _columnIndex;
|
||||
}
|
||||
}
|
||||
|
@ -1,162 +1,162 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.model.HSSFFormulaParser;
|
||||
import org.apache.poi.hssf.model.Workbook;
|
||||
import org.apache.poi.hssf.record.NameRecord;
|
||||
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.ss.formula.*;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
|
||||
/**
|
||||
* Internal POI use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {
|
||||
|
||||
private final HSSFWorkbook _uBook;
|
||||
private final Workbook _iBook;
|
||||
|
||||
public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {
|
||||
if (book == null) {
|
||||
return null;
|
||||
}
|
||||
return new HSSFEvaluationWorkbook(book);
|
||||
}
|
||||
|
||||
private HSSFEvaluationWorkbook(HSSFWorkbook book) {
|
||||
_uBook = book;
|
||||
_iBook = book.getWorkbook();
|
||||
}
|
||||
|
||||
public int getExternalSheetIndex(String sheetName) {
|
||||
int sheetIndex = _uBook.getSheetIndex(sheetName);
|
||||
return _iBook.checkExternSheet(sheetIndex);
|
||||
}
|
||||
public int getExternalSheetIndex(String workbookName, String sheetName) {
|
||||
return _iBook.getExternalSheetIndex(workbookName, sheetName);
|
||||
}
|
||||
|
||||
public NameXPtg getNameXPtg(String name) {
|
||||
return _iBook.getNameXPtg(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a named range by its name.
|
||||
*
|
||||
* @param name the name to search
|
||||
* @param sheetIndex the 0-based index of the sheet this formula belongs to.
|
||||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means workbook-global names
|
||||
*/
|
||||
public EvaluationName getName(String name, int sheetIndex) {
|
||||
for(int i=0; i < _iBook.getNumNames(); i++) {
|
||||
NameRecord nr = _iBook.getNameRecord(i);
|
||||
if (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) {
|
||||
return new Name(nr, i);
|
||||
}
|
||||
}
|
||||
return sheetIndex == -1 ? null : getName(name, -1);
|
||||
}
|
||||
|
||||
public int getSheetIndex(EvaluationSheet evalSheet) {
|
||||
HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet();
|
||||
return _uBook.getSheetIndex(sheet);
|
||||
}
|
||||
public int getSheetIndex(String sheetName) {
|
||||
return _uBook.getSheetIndex(sheetName);
|
||||
}
|
||||
|
||||
public String getSheetName(int sheetIndex) {
|
||||
return _uBook.getSheetName(sheetIndex);
|
||||
}
|
||||
|
||||
public EvaluationSheet getSheet(int sheetIndex) {
|
||||
return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
|
||||
}
|
||||
public int convertFromExternSheetIndex(int externSheetIndex) {
|
||||
return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex);
|
||||
}
|
||||
|
||||
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||
return _iBook.getExternalSheet(externSheetIndex);
|
||||
}
|
||||
|
||||
public String resolveNameXText(NameXPtg n) {
|
||||
return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
|
||||
}
|
||||
|
||||
public String getSheetNameByExternSheet(int externSheetIndex) {
|
||||
return _iBook.findSheetNameFromExternSheet(externSheetIndex);
|
||||
}
|
||||
public String getNameText(NamePtg namePtg) {
|
||||
return _iBook.getNameRecord(namePtg.getIndex()).getNameText();
|
||||
}
|
||||
public EvaluationName getName(NamePtg namePtg) {
|
||||
int ix = namePtg.getIndex();
|
||||
return new Name(_iBook.getNameRecord(ix), ix);
|
||||
}
|
||||
public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
|
||||
HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
|
||||
if (false) {
|
||||
// re-parsing the formula text also works, but is a waste of time
|
||||
// It is useful from time to time to run all unit tests with this code
|
||||
// to make sure that all formulas POI can evaluate can also be parsed.
|
||||
return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
|
||||
}
|
||||
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
|
||||
return fra.getFormulaTokens();
|
||||
}
|
||||
|
||||
private static final class Name implements EvaluationName {
|
||||
|
||||
private final NameRecord _nameRecord;
|
||||
private final int _index;
|
||||
|
||||
public Name(NameRecord nameRecord, int index) {
|
||||
_nameRecord = nameRecord;
|
||||
_index = index;
|
||||
}
|
||||
public Ptg[] getNameDefinition() {
|
||||
return _nameRecord.getNameDefinition();
|
||||
}
|
||||
public String getNameText() {
|
||||
return _nameRecord.getNameText();
|
||||
}
|
||||
public boolean hasFormula() {
|
||||
return _nameRecord.hasFormula();
|
||||
}
|
||||
public boolean isFunctionName() {
|
||||
return _nameRecord.isFunctionName();
|
||||
}
|
||||
public boolean isRange() {
|
||||
return _nameRecord.hasFormula(); // TODO - is this right?
|
||||
}
|
||||
public NamePtg createPtg() {
|
||||
return new NamePtg(_index);
|
||||
}
|
||||
}
|
||||
|
||||
public SpreadsheetVersion getSpreadsheetVersion(){
|
||||
return SpreadsheetVersion.EXCEL97;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.model.HSSFFormulaParser;
|
||||
import org.apache.poi.hssf.model.Workbook;
|
||||
import org.apache.poi.hssf.record.NameRecord;
|
||||
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.ss.formula.*;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
|
||||
/**
|
||||
* Internal POI use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {
|
||||
|
||||
private final HSSFWorkbook _uBook;
|
||||
private final Workbook _iBook;
|
||||
|
||||
public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {
|
||||
if (book == null) {
|
||||
return null;
|
||||
}
|
||||
return new HSSFEvaluationWorkbook(book);
|
||||
}
|
||||
|
||||
private HSSFEvaluationWorkbook(HSSFWorkbook book) {
|
||||
_uBook = book;
|
||||
_iBook = book.getWorkbook();
|
||||
}
|
||||
|
||||
public int getExternalSheetIndex(String sheetName) {
|
||||
int sheetIndex = _uBook.getSheetIndex(sheetName);
|
||||
return _iBook.checkExternSheet(sheetIndex);
|
||||
}
|
||||
public int getExternalSheetIndex(String workbookName, String sheetName) {
|
||||
return _iBook.getExternalSheetIndex(workbookName, sheetName);
|
||||
}
|
||||
|
||||
public NameXPtg getNameXPtg(String name) {
|
||||
return _iBook.getNameXPtg(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a named range by its name.
|
||||
*
|
||||
* @param name the name to search
|
||||
* @param sheetIndex the 0-based index of the sheet this formula belongs to.
|
||||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means workbook-global names
|
||||
*/
|
||||
public EvaluationName getName(String name, int sheetIndex) {
|
||||
for(int i=0; i < _iBook.getNumNames(); i++) {
|
||||
NameRecord nr = _iBook.getNameRecord(i);
|
||||
if (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) {
|
||||
return new Name(nr, i);
|
||||
}
|
||||
}
|
||||
return sheetIndex == -1 ? null : getName(name, -1);
|
||||
}
|
||||
|
||||
public int getSheetIndex(EvaluationSheet evalSheet) {
|
||||
HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet();
|
||||
return _uBook.getSheetIndex(sheet);
|
||||
}
|
||||
public int getSheetIndex(String sheetName) {
|
||||
return _uBook.getSheetIndex(sheetName);
|
||||
}
|
||||
|
||||
public String getSheetName(int sheetIndex) {
|
||||
return _uBook.getSheetName(sheetIndex);
|
||||
}
|
||||
|
||||
public EvaluationSheet getSheet(int sheetIndex) {
|
||||
return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
|
||||
}
|
||||
public int convertFromExternSheetIndex(int externSheetIndex) {
|
||||
return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex);
|
||||
}
|
||||
|
||||
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||
return _iBook.getExternalSheet(externSheetIndex);
|
||||
}
|
||||
|
||||
public String resolveNameXText(NameXPtg n) {
|
||||
return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
|
||||
}
|
||||
|
||||
public String getSheetNameByExternSheet(int externSheetIndex) {
|
||||
return _iBook.findSheetNameFromExternSheet(externSheetIndex);
|
||||
}
|
||||
public String getNameText(NamePtg namePtg) {
|
||||
return _iBook.getNameRecord(namePtg.getIndex()).getNameText();
|
||||
}
|
||||
public EvaluationName getName(NamePtg namePtg) {
|
||||
int ix = namePtg.getIndex();
|
||||
return new Name(_iBook.getNameRecord(ix), ix);
|
||||
}
|
||||
public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
|
||||
HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
|
||||
if (false) {
|
||||
// re-parsing the formula text also works, but is a waste of time
|
||||
// It is useful from time to time to run all unit tests with this code
|
||||
// to make sure that all formulas POI can evaluate can also be parsed.
|
||||
return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
|
||||
}
|
||||
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
|
||||
return fra.getFormulaTokens();
|
||||
}
|
||||
|
||||
private static final class Name implements EvaluationName {
|
||||
|
||||
private final NameRecord _nameRecord;
|
||||
private final int _index;
|
||||
|
||||
public Name(NameRecord nameRecord, int index) {
|
||||
_nameRecord = nameRecord;
|
||||
_index = index;
|
||||
}
|
||||
public Ptg[] getNameDefinition() {
|
||||
return _nameRecord.getNameDefinition();
|
||||
}
|
||||
public String getNameText() {
|
||||
return _nameRecord.getNameText();
|
||||
}
|
||||
public boolean hasFormula() {
|
||||
return _nameRecord.hasFormula();
|
||||
}
|
||||
public boolean isFunctionName() {
|
||||
return _nameRecord.isFunctionName();
|
||||
}
|
||||
public boolean isRange() {
|
||||
return _nameRecord.hasFormula(); // TODO - is this right?
|
||||
}
|
||||
public NamePtg createPtg() {
|
||||
return new NamePtg(_index);
|
||||
}
|
||||
}
|
||||
|
||||
public SpreadsheetVersion getSpreadsheetVersion(){
|
||||
return SpreadsheetVersion.EXCEL97;
|
||||
}
|
||||
}
|
||||
|
@ -1,315 +1,316 @@
|
||||
/* ====================================================================
|
||||
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 java.util.Iterator;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
|
||||
import org.apache.poi.ss.formula.IStabilityClassifier;
|
||||
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellValue;
|
||||
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||
|
||||
/**
|
||||
* Evaluates formula cells.<p/>
|
||||
*
|
||||
* For performance reasons, this class keeps a cache of all previously calculated intermediate
|
||||
* cell values. Be sure to call {@link #clearAllCachedResultValues()} if any workbook cells are changed between
|
||||
* calls to evaluate~ methods on this class.
|
||||
*
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class HSSFFormulaEvaluator implements FormulaEvaluator {
|
||||
|
||||
private WorkbookEvaluator _bookEvaluator;
|
||||
|
||||
/**
|
||||
* @deprecated (Sep 2008) HSSFSheet parameter is ignored
|
||||
*/
|
||||
public HSSFFormulaEvaluator(HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
this(workbook);
|
||||
if (false) {
|
||||
sheet.toString(); // suppress unused parameter compiler warning
|
||||
}
|
||||
}
|
||||
public HSSFFormulaEvaluator(HSSFWorkbook workbook) {
|
||||
this(workbook, null);
|
||||
}
|
||||
/**
|
||||
* @param stabilityClassifier used to optimise caching performance. Pass <code>null</code>
|
||||
* for the (conservative) assumption that any cell may have its definition changed after
|
||||
* evaluation begins.
|
||||
*/
|
||||
public HSSFFormulaEvaluator(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier) {
|
||||
_bookEvaluator = new WorkbookEvaluator(HSSFEvaluationWorkbook.create(workbook), stabilityClassifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Coordinates several formula evaluators together so that formulas that involve external
|
||||
* references can be evaluated.
|
||||
* @param workbookNames the simple file names used to identify the workbooks in formulas
|
||||
* with external links (for example "MyData.xls" as used in a formula "[MyData.xls]Sheet1!A1")
|
||||
* @param evaluators all evaluators for the full set of workbooks required by the formulas.
|
||||
*/
|
||||
public static void setupEnvironment(String[] workbookNames, HSSFFormulaEvaluator[] evaluators) {
|
||||
WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];
|
||||
for (int i = 0; i < wbEvals.length; i++) {
|
||||
wbEvals[i] = evaluators[i]._bookEvaluator;
|
||||
}
|
||||
CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing
|
||||
* @deprecated (Aug 2008) - not needed, since the current row can be derived from the cell
|
||||
*/
|
||||
public void setCurrentRow(HSSFRow row) {
|
||||
// do nothing
|
||||
if (false) {
|
||||
row.getClass(); // suppress unused parameter compiler warning
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called whenever there are major changes (e.g. moving sheets) to input cells
|
||||
* in the evaluated workbook. If performance is not critical, a single call to this method
|
||||
* may be used instead of many specific calls to the notify~ methods.
|
||||
*
|
||||
* Failure to call this method after changing cell values will cause incorrect behaviour
|
||||
* of the evaluate~ methods of this class
|
||||
*/
|
||||
public void clearAllCachedResultValues() {
|
||||
_bookEvaluator.clearAllCachedResultValues();
|
||||
}
|
||||
/**
|
||||
* Should be called to tell the cell value cache that the specified (value or formula) cell
|
||||
* has changed.
|
||||
* Failure to call this method after changing cell values will cause incorrect behaviour
|
||||
* of the evaluate~ methods of this class
|
||||
*/
|
||||
public void notifyUpdateCell(HSSFCell cell) {
|
||||
_bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell(cell));
|
||||
}
|
||||
/**
|
||||
* Should be called to tell the cell value cache that the specified cell has just been
|
||||
* deleted.
|
||||
* Failure to call this method after changing cell values will cause incorrect behaviour
|
||||
* of the evaluate~ methods of this class
|
||||
*/
|
||||
public void notifyDeleteCell(HSSFCell cell) {
|
||||
_bookEvaluator.notifyDeleteCell(new HSSFEvaluationCell(cell));
|
||||
}
|
||||
public void notifyDeleteCell(Cell cell) {
|
||||
_bookEvaluator.notifyDeleteCell(new HSSFEvaluationCell((HSSFCell)cell));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called to tell the cell value cache that the specified (value or formula) cell
|
||||
* has changed.
|
||||
* Failure to call this method after changing cell values will cause incorrect behaviour
|
||||
* of the evaluate~ methods of this class
|
||||
*/
|
||||
public void notifySetFormula(Cell cell) {
|
||||
_bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell((HSSFCell)cell));
|
||||
}
|
||||
|
||||
/**
|
||||
* If cell contains a formula, the formula is evaluated and returned,
|
||||
* else the CellValue simply copies the appropriate cell value from
|
||||
* the cell and also its cell type. This method should be preferred over
|
||||
* evaluateInCell() when the call should not modify the contents of the
|
||||
* original cell.
|
||||
*
|
||||
* @param cell may be <code>null</code> signifying that the cell is not present (or blank)
|
||||
* @return <code>null</code> if the supplied cell is <code>null</code> or blank
|
||||
*/
|
||||
public CellValue evaluate(Cell cell) {
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
return CellValue.valueOf(cell.getBooleanCellValue());
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
return CellValue.getError(cell.getErrorCellValue());
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
return evaluateFormulaCellValue(cell);
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
return new CellValue(cell.getNumericCellValue());
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
return new CellValue(cell.getRichStringCellValue().getString());
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
return null;
|
||||
}
|
||||
throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If cell contains formula, it evaluates the formula, and saves the result of the formula. The
|
||||
* cell remains as a formula cell. If the cell does not contain formula, this method returns -1
|
||||
* and leaves the cell unchanged.
|
||||
*
|
||||
* Note that the type of the <em>formula result</em> is returned, so you know what kind of
|
||||
* cached formula result is also stored with the formula.
|
||||
* <pre>
|
||||
* int evaluatedCellType = evaluator.evaluateFormulaCell(cell);
|
||||
* </pre>
|
||||
* Be aware that your cell will hold both the formula, and the result. If you want the cell
|
||||
* replaced with the result of the formula, use {@link #evaluateInCell(org.apache.poi.ss.usermodel.Cell)}
|
||||
* @param cell The cell to evaluate
|
||||
* @return -1 for non-formula cells, or the type of the <em>formula result</em>
|
||||
*/
|
||||
public int evaluateFormulaCell(Cell cell) {
|
||||
if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
|
||||
return -1;
|
||||
}
|
||||
CellValue cv = evaluateFormulaCellValue(cell);
|
||||
// cell remains a formula cell, but the cached value is changed
|
||||
setCellValue(cell, cv);
|
||||
return cv.getCellType();
|
||||
}
|
||||
|
||||
/**
|
||||
* If cell contains formula, it evaluates the formula, and
|
||||
* puts the formula result back into the cell, in place
|
||||
* of the old formula.
|
||||
* Else if cell does not contain formula, this method leaves
|
||||
* the cell unchanged.
|
||||
* Note that the same instance of HSSFCell is returned to
|
||||
* allow chained calls like:
|
||||
* <pre>
|
||||
* int evaluatedCellType = evaluator.evaluateInCell(cell).getCellType();
|
||||
* </pre>
|
||||
* Be aware that your cell value will be changed to hold the
|
||||
* result of the formula. If you simply want the formula
|
||||
* value computed for you, use {@link #evaluateFormulaCell(Cell)}}
|
||||
*/
|
||||
public HSSFCell evaluateInCell(Cell cell) {
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
HSSFCell result = (HSSFCell) cell;
|
||||
if (cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
|
||||
CellValue cv = evaluateFormulaCellValue(cell);
|
||||
setCellValue(cell, cv);
|
||||
setCellType(cell, cv); // cell will no longer be a formula cell
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private static void setCellType(Cell cell, CellValue cv) {
|
||||
int cellType = cv.getCellType();
|
||||
switch (cellType) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
cell.setCellType(cellType);
|
||||
return;
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
// never happens - blanks eventually get translated to zero
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
// this will never happen, we have already evaluated the formula
|
||||
}
|
||||
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
|
||||
}
|
||||
|
||||
private static void setCellValue(Cell cell, CellValue cv) {
|
||||
int cellType = cv.getCellType();
|
||||
switch (cellType) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
cell.setCellValue(cv.getBooleanValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
cell.setCellErrorValue(cv.getErrorValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
cell.setCellValue(cv.getNumberValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
cell.setCellValue(new HSSFRichTextString(cv.getStringValue()));
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
// never happens - blanks eventually get translated to zero
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
// this will never happen, we have already evaluated the formula
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops over all cells in all sheets of the supplied
|
||||
* workbook.
|
||||
* For cells that contain formulas, their formulas are
|
||||
* evaluated, and the results are saved. These cells
|
||||
* remain as formula cells.
|
||||
* For cells that do not contain formulas, no changes
|
||||
* are made.
|
||||
* This is a helpful wrapper around looping over all
|
||||
* cells, and calling evaluateFormulaCell on each one.
|
||||
*/
|
||||
public static void evaluateAllFormulaCells(HSSFWorkbook wb) {
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
for(int i=0; i<wb.getNumberOfSheets(); i++) {
|
||||
HSSFSheet sheet = wb.getSheetAt(i);
|
||||
|
||||
for (Iterator rit = sheet.rowIterator(); rit.hasNext();) {
|
||||
HSSFRow r = (HSSFRow)rit.next();
|
||||
|
||||
for (Iterator cit = r.cellIterator(); cit.hasNext();) {
|
||||
HSSFCell c = (HSSFCell)cit.next();
|
||||
if (c.getCellType() == HSSFCell.CELL_TYPE_FORMULA)
|
||||
evaluator.evaluateFormulaCell(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CellValue wrapper around the supplied ValueEval instance.
|
||||
* @param eval
|
||||
*/
|
||||
private CellValue evaluateFormulaCellValue(Cell cell) {
|
||||
ValueEval eval = _bookEvaluator.evaluate(new HSSFEvaluationCell((HSSFCell)cell));
|
||||
if (eval instanceof NumberEval) {
|
||||
NumberEval ne = (NumberEval) eval;
|
||||
return new CellValue(ne.getNumberValue());
|
||||
}
|
||||
if (eval instanceof BoolEval) {
|
||||
BoolEval be = (BoolEval) eval;
|
||||
return CellValue.valueOf(be.getBooleanValue());
|
||||
}
|
||||
if (eval instanceof StringEval) {
|
||||
StringEval ne = (StringEval) eval;
|
||||
return new CellValue(ne.getStringValue());
|
||||
}
|
||||
if (eval instanceof ErrorEval) {
|
||||
return CellValue.getError(((ErrorEval)eval).getErrorCode());
|
||||
}
|
||||
throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")");
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
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 java.util.Iterator;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
|
||||
import org.apache.poi.ss.formula.IStabilityClassifier;
|
||||
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellValue;
|
||||
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
|
||||
/**
|
||||
* Evaluates formula cells.<p/>
|
||||
*
|
||||
* For performance reasons, this class keeps a cache of all previously calculated intermediate
|
||||
* cell values. Be sure to call {@link #clearAllCachedResultValues()} if any workbook cells are changed between
|
||||
* calls to evaluate~ methods on this class.
|
||||
*
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class HSSFFormulaEvaluator implements FormulaEvaluator {
|
||||
|
||||
private WorkbookEvaluator _bookEvaluator;
|
||||
|
||||
/**
|
||||
* @deprecated (Sep 2008) HSSFSheet parameter is ignored
|
||||
*/
|
||||
public HSSFFormulaEvaluator(HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
this(workbook);
|
||||
if (false) {
|
||||
sheet.toString(); // suppress unused parameter compiler warning
|
||||
}
|
||||
}
|
||||
public HSSFFormulaEvaluator(HSSFWorkbook workbook) {
|
||||
this(workbook, null);
|
||||
}
|
||||
/**
|
||||
* @param stabilityClassifier used to optimise caching performance. Pass <code>null</code>
|
||||
* for the (conservative) assumption that any cell may have its definition changed after
|
||||
* evaluation begins.
|
||||
*/
|
||||
public HSSFFormulaEvaluator(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier) {
|
||||
_bookEvaluator = new WorkbookEvaluator(HSSFEvaluationWorkbook.create(workbook), stabilityClassifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Coordinates several formula evaluators together so that formulas that involve external
|
||||
* references can be evaluated.
|
||||
* @param workbookNames the simple file names used to identify the workbooks in formulas
|
||||
* with external links (for example "MyData.xls" as used in a formula "[MyData.xls]Sheet1!A1")
|
||||
* @param evaluators all evaluators for the full set of workbooks required by the formulas.
|
||||
*/
|
||||
public static void setupEnvironment(String[] workbookNames, HSSFFormulaEvaluator[] evaluators) {
|
||||
WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];
|
||||
for (int i = 0; i < wbEvals.length; i++) {
|
||||
wbEvals[i] = evaluators[i]._bookEvaluator;
|
||||
}
|
||||
CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing
|
||||
* @deprecated (Aug 2008) - not needed, since the current row can be derived from the cell
|
||||
*/
|
||||
public void setCurrentRow(HSSFRow row) {
|
||||
// do nothing
|
||||
if (false) {
|
||||
row.getClass(); // suppress unused parameter compiler warning
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called whenever there are major changes (e.g. moving sheets) to input cells
|
||||
* in the evaluated workbook. If performance is not critical, a single call to this method
|
||||
* may be used instead of many specific calls to the notify~ methods.
|
||||
*
|
||||
* Failure to call this method after changing cell values will cause incorrect behaviour
|
||||
* of the evaluate~ methods of this class
|
||||
*/
|
||||
public void clearAllCachedResultValues() {
|
||||
_bookEvaluator.clearAllCachedResultValues();
|
||||
}
|
||||
/**
|
||||
* Should be called to tell the cell value cache that the specified (value or formula) cell
|
||||
* has changed.
|
||||
* Failure to call this method after changing cell values will cause incorrect behaviour
|
||||
* of the evaluate~ methods of this class
|
||||
*/
|
||||
public void notifyUpdateCell(HSSFCell cell) {
|
||||
_bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell(cell));
|
||||
}
|
||||
/**
|
||||
* Should be called to tell the cell value cache that the specified cell has just been
|
||||
* deleted.
|
||||
* Failure to call this method after changing cell values will cause incorrect behaviour
|
||||
* of the evaluate~ methods of this class
|
||||
*/
|
||||
public void notifyDeleteCell(HSSFCell cell) {
|
||||
_bookEvaluator.notifyDeleteCell(new HSSFEvaluationCell(cell));
|
||||
}
|
||||
public void notifyDeleteCell(Cell cell) {
|
||||
_bookEvaluator.notifyDeleteCell(new HSSFEvaluationCell((HSSFCell)cell));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called to tell the cell value cache that the specified (value or formula) cell
|
||||
* has changed.
|
||||
* Failure to call this method after changing cell values will cause incorrect behaviour
|
||||
* of the evaluate~ methods of this class
|
||||
*/
|
||||
public void notifySetFormula(Cell cell) {
|
||||
_bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell((HSSFCell)cell));
|
||||
}
|
||||
|
||||
/**
|
||||
* If cell contains a formula, the formula is evaluated and returned,
|
||||
* else the CellValue simply copies the appropriate cell value from
|
||||
* the cell and also its cell type. This method should be preferred over
|
||||
* evaluateInCell() when the call should not modify the contents of the
|
||||
* original cell.
|
||||
*
|
||||
* @param cell may be <code>null</code> signifying that the cell is not present (or blank)
|
||||
* @return <code>null</code> if the supplied cell is <code>null</code> or blank
|
||||
*/
|
||||
public CellValue evaluate(Cell cell) {
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
return CellValue.valueOf(cell.getBooleanCellValue());
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
return CellValue.getError(cell.getErrorCellValue());
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
return evaluateFormulaCellValue(cell);
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
return new CellValue(cell.getNumericCellValue());
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
return new CellValue(cell.getRichStringCellValue().getString());
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
return null;
|
||||
}
|
||||
throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If cell contains formula, it evaluates the formula, and saves the result of the formula. The
|
||||
* cell remains as a formula cell. If the cell does not contain formula, this method returns -1
|
||||
* and leaves the cell unchanged.
|
||||
*
|
||||
* Note that the type of the <em>formula result</em> is returned, so you know what kind of
|
||||
* cached formula result is also stored with the formula.
|
||||
* <pre>
|
||||
* int evaluatedCellType = evaluator.evaluateFormulaCell(cell);
|
||||
* </pre>
|
||||
* Be aware that your cell will hold both the formula, and the result. If you want the cell
|
||||
* replaced with the result of the formula, use {@link #evaluateInCell(org.apache.poi.ss.usermodel.Cell)}
|
||||
* @param cell The cell to evaluate
|
||||
* @return -1 for non-formula cells, or the type of the <em>formula result</em>
|
||||
*/
|
||||
public int evaluateFormulaCell(Cell cell) {
|
||||
if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
|
||||
return -1;
|
||||
}
|
||||
CellValue cv = evaluateFormulaCellValue(cell);
|
||||
// cell remains a formula cell, but the cached value is changed
|
||||
setCellValue(cell, cv);
|
||||
return cv.getCellType();
|
||||
}
|
||||
|
||||
/**
|
||||
* If cell contains formula, it evaluates the formula, and
|
||||
* puts the formula result back into the cell, in place
|
||||
* of the old formula.
|
||||
* Else if cell does not contain formula, this method leaves
|
||||
* the cell unchanged.
|
||||
* Note that the same instance of HSSFCell is returned to
|
||||
* allow chained calls like:
|
||||
* <pre>
|
||||
* int evaluatedCellType = evaluator.evaluateInCell(cell).getCellType();
|
||||
* </pre>
|
||||
* Be aware that your cell value will be changed to hold the
|
||||
* result of the formula. If you simply want the formula
|
||||
* value computed for you, use {@link #evaluateFormulaCell(Cell)}}
|
||||
*/
|
||||
public HSSFCell evaluateInCell(Cell cell) {
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
HSSFCell result = (HSSFCell) cell;
|
||||
if (cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
|
||||
CellValue cv = evaluateFormulaCellValue(cell);
|
||||
setCellValue(cell, cv);
|
||||
setCellType(cell, cv); // cell will no longer be a formula cell
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private static void setCellType(Cell cell, CellValue cv) {
|
||||
int cellType = cv.getCellType();
|
||||
switch (cellType) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
cell.setCellType(cellType);
|
||||
return;
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
// never happens - blanks eventually get translated to zero
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
// this will never happen, we have already evaluated the formula
|
||||
}
|
||||
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
|
||||
}
|
||||
|
||||
private static void setCellValue(Cell cell, CellValue cv) {
|
||||
int cellType = cv.getCellType();
|
||||
switch (cellType) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
cell.setCellValue(cv.getBooleanValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
cell.setCellErrorValue(cv.getErrorValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
cell.setCellValue(cv.getNumberValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
cell.setCellValue(new HSSFRichTextString(cv.getStringValue()));
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
// never happens - blanks eventually get translated to zero
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
// this will never happen, we have already evaluated the formula
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops over all cells in all sheets of the supplied
|
||||
* workbook.
|
||||
* For cells that contain formulas, their formulas are
|
||||
* evaluated, and the results are saved. These cells
|
||||
* remain as formula cells.
|
||||
* For cells that do not contain formulas, no changes
|
||||
* are made.
|
||||
* This is a helpful wrapper around looping over all
|
||||
* cells, and calling evaluateFormulaCell on each one.
|
||||
*/
|
||||
public static void evaluateAllFormulaCells(HSSFWorkbook wb) {
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
for(int i=0; i<wb.getNumberOfSheets(); i++) {
|
||||
HSSFSheet sheet = wb.getSheetAt(i);
|
||||
|
||||
for (Iterator<Row> rit = sheet.rowIterator(); rit.hasNext();) {
|
||||
Row r = rit.next();
|
||||
|
||||
for (Iterator<Cell> cit = r.cellIterator(); cit.hasNext();) {
|
||||
Cell c = cit.next();
|
||||
if (c.getCellType() == HSSFCell.CELL_TYPE_FORMULA)
|
||||
evaluator.evaluateFormulaCell(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CellValue wrapper around the supplied ValueEval instance.
|
||||
* @param eval
|
||||
*/
|
||||
private CellValue evaluateFormulaCellValue(Cell cell) {
|
||||
ValueEval eval = _bookEvaluator.evaluate(new HSSFEvaluationCell((HSSFCell)cell));
|
||||
if (eval instanceof NumberEval) {
|
||||
NumberEval ne = (NumberEval) eval;
|
||||
return new CellValue(ne.getNumberValue());
|
||||
}
|
||||
if (eval instanceof BoolEval) {
|
||||
BoolEval be = (BoolEval) eval;
|
||||
return CellValue.valueOf(be.getBooleanValue());
|
||||
}
|
||||
if (eval instanceof StringEval) {
|
||||
StringEval ne = (StringEval) eval;
|
||||
return new CellValue(ne.getStringValue());
|
||||
}
|
||||
if (eval instanceof ErrorEval) {
|
||||
return CellValue.getError(((ErrorEval)eval).getErrorCode());
|
||||
}
|
||||
throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")");
|
||||
}
|
||||
}
|
||||
|
@ -1,220 +1,220 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.HyperlinkRecord;
|
||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||
|
||||
/**
|
||||
* Represents an Excel hyperlink.
|
||||
*
|
||||
* @author Yegor Kozlov (yegor at apache dot org)
|
||||
*/
|
||||
public class HSSFHyperlink implements Hyperlink {
|
||||
|
||||
/**
|
||||
* Link to a existing file or web page
|
||||
*/
|
||||
public static final int LINK_URL = 1;
|
||||
|
||||
/**
|
||||
* Link to a place in this document
|
||||
*/
|
||||
public static final int LINK_DOCUMENT = 2;
|
||||
|
||||
/**
|
||||
* Link to an E-mail address
|
||||
*/
|
||||
public static final int LINK_EMAIL = 3;
|
||||
|
||||
/**
|
||||
* Link to a file
|
||||
*/
|
||||
public static final int LINK_FILE = 4;
|
||||
|
||||
/**
|
||||
* Low-level record object that stores the actual hyperlink data
|
||||
*/
|
||||
protected HyperlinkRecord record = null;
|
||||
|
||||
/**
|
||||
* If we create a new hypelrink remember its type
|
||||
*/
|
||||
protected int link_type;
|
||||
|
||||
/**
|
||||
* Construct a new hyperlink
|
||||
*
|
||||
* @param type the type of hyperlink to create
|
||||
*/
|
||||
public HSSFHyperlink( int type )
|
||||
{
|
||||
this.link_type = type;
|
||||
record = new HyperlinkRecord();
|
||||
switch(type){
|
||||
case LINK_URL:
|
||||
case LINK_EMAIL:
|
||||
record.newUrlLink();
|
||||
break;
|
||||
case LINK_FILE:
|
||||
record.newFileLink();
|
||||
break;
|
||||
case LINK_DOCUMENT:
|
||||
record.newDocumentLink();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the hyperlink by a <code>HyperlinkRecord</code> record
|
||||
*
|
||||
* @param record
|
||||
*/
|
||||
protected HSSFHyperlink( HyperlinkRecord record )
|
||||
{
|
||||
this.record = record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the row of the first cell that contains the hyperlink
|
||||
*
|
||||
* @return the 0-based row of the cell that contains the hyperlink
|
||||
*/
|
||||
public int getFirstRow(){
|
||||
return record.getFirstRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the row of the first cell that contains the hyperlink
|
||||
*
|
||||
* @param row the 0-based row of the first cell that contains the hyperlink
|
||||
*/
|
||||
public void setFirstRow(int row){
|
||||
record.setFirstRow(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the row of the last cell that contains the hyperlink
|
||||
*
|
||||
* @return the 0-based row of the last cell that contains the hyperlink
|
||||
*/
|
||||
public int getLastRow(){
|
||||
return record.getLastRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the row of the last cell that contains the hyperlink
|
||||
*
|
||||
* @param row the 0-based row of the last cell that contains the hyperlink
|
||||
*/
|
||||
public void setLastRow(int row){
|
||||
record.setLastRow(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column of the first cell that contains the hyperlink
|
||||
*
|
||||
* @return the 0-based column of the first cell that contains the hyperlink
|
||||
*/
|
||||
public int getFirstColumn(){
|
||||
return record.getFirstColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the column of the first cell that contains the hyperlink
|
||||
*
|
||||
* @param col the 0-based column of the first cell that contains the hyperlink
|
||||
*/
|
||||
public void setFirstColumn(int col){
|
||||
record.setFirstColumn((short)col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column of the last cell that contains the hyperlink
|
||||
*
|
||||
* @return the 0-based column of the last cell that contains the hyperlink
|
||||
*/
|
||||
public int getLastColumn(){
|
||||
return record.getLastColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the column of the last cell that contains the hyperlink
|
||||
*
|
||||
* @param col the 0-based column of the last cell that contains the hyperlink
|
||||
*/
|
||||
public void setLastColumn(int col){
|
||||
record.setLastColumn((short)col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hypelink address. Depending on the hyperlink type it can be URL, e-mail, patrh to a file, etc.
|
||||
*
|
||||
* @return the address of this hyperlink
|
||||
*/
|
||||
public String getAddress(){
|
||||
return record.getAddress();
|
||||
}
|
||||
public String getTextMark(){
|
||||
return record.getTextMark();
|
||||
}
|
||||
public void setTextMark(String textMark) {
|
||||
record.setTextMark(textMark);
|
||||
}
|
||||
public String getShortFilename(){
|
||||
return record.getShortFilename();
|
||||
}
|
||||
public void setShortFilename(String shortFilename) {
|
||||
record.setShortFilename(shortFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hypelink address. Depending on the hyperlink type it can be URL, e-mail, patrh to a file, etc.
|
||||
*
|
||||
* @param address the address of this hyperlink
|
||||
*/
|
||||
public void setAddress(String address){
|
||||
record.setAddress(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return text label for this hyperlink
|
||||
*
|
||||
* @return text to display
|
||||
*/
|
||||
public String getLabel(){
|
||||
return record.getLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets text label for this hyperlink
|
||||
*
|
||||
* @param label text label for this hyperlink
|
||||
*/
|
||||
public void setLabel(String label){
|
||||
record.setLabel(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of this hyperlink
|
||||
*
|
||||
* @return the type of this hyperlink
|
||||
*/
|
||||
public int getType(){
|
||||
return link_type;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.HyperlinkRecord;
|
||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||
|
||||
/**
|
||||
* Represents an Excel hyperlink.
|
||||
*
|
||||
* @author Yegor Kozlov (yegor at apache dot org)
|
||||
*/
|
||||
public class HSSFHyperlink implements Hyperlink {
|
||||
|
||||
/**
|
||||
* Link to a existing file or web page
|
||||
*/
|
||||
public static final int LINK_URL = 1;
|
||||
|
||||
/**
|
||||
* Link to a place in this document
|
||||
*/
|
||||
public static final int LINK_DOCUMENT = 2;
|
||||
|
||||
/**
|
||||
* Link to an E-mail address
|
||||
*/
|
||||
public static final int LINK_EMAIL = 3;
|
||||
|
||||
/**
|
||||
* Link to a file
|
||||
*/
|
||||
public static final int LINK_FILE = 4;
|
||||
|
||||
/**
|
||||
* Low-level record object that stores the actual hyperlink data
|
||||
*/
|
||||
protected HyperlinkRecord record = null;
|
||||
|
||||
/**
|
||||
* If we create a new hypelrink remember its type
|
||||
*/
|
||||
protected int link_type;
|
||||
|
||||
/**
|
||||
* Construct a new hyperlink
|
||||
*
|
||||
* @param type the type of hyperlink to create
|
||||
*/
|
||||
public HSSFHyperlink( int type )
|
||||
{
|
||||
this.link_type = type;
|
||||
record = new HyperlinkRecord();
|
||||
switch(type){
|
||||
case LINK_URL:
|
||||
case LINK_EMAIL:
|
||||
record.newUrlLink();
|
||||
break;
|
||||
case LINK_FILE:
|
||||
record.newFileLink();
|
||||
break;
|
||||
case LINK_DOCUMENT:
|
||||
record.newDocumentLink();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the hyperlink by a <code>HyperlinkRecord</code> record
|
||||
*
|
||||
* @param record
|
||||
*/
|
||||
protected HSSFHyperlink( HyperlinkRecord record )
|
||||
{
|
||||
this.record = record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the row of the first cell that contains the hyperlink
|
||||
*
|
||||
* @return the 0-based row of the cell that contains the hyperlink
|
||||
*/
|
||||
public int getFirstRow(){
|
||||
return record.getFirstRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the row of the first cell that contains the hyperlink
|
||||
*
|
||||
* @param row the 0-based row of the first cell that contains the hyperlink
|
||||
*/
|
||||
public void setFirstRow(int row){
|
||||
record.setFirstRow(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the row of the last cell that contains the hyperlink
|
||||
*
|
||||
* @return the 0-based row of the last cell that contains the hyperlink
|
||||
*/
|
||||
public int getLastRow(){
|
||||
return record.getLastRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the row of the last cell that contains the hyperlink
|
||||
*
|
||||
* @param row the 0-based row of the last cell that contains the hyperlink
|
||||
*/
|
||||
public void setLastRow(int row){
|
||||
record.setLastRow(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column of the first cell that contains the hyperlink
|
||||
*
|
||||
* @return the 0-based column of the first cell that contains the hyperlink
|
||||
*/
|
||||
public int getFirstColumn(){
|
||||
return record.getFirstColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the column of the first cell that contains the hyperlink
|
||||
*
|
||||
* @param col the 0-based column of the first cell that contains the hyperlink
|
||||
*/
|
||||
public void setFirstColumn(int col){
|
||||
record.setFirstColumn((short)col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column of the last cell that contains the hyperlink
|
||||
*
|
||||
* @return the 0-based column of the last cell that contains the hyperlink
|
||||
*/
|
||||
public int getLastColumn(){
|
||||
return record.getLastColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the column of the last cell that contains the hyperlink
|
||||
*
|
||||
* @param col the 0-based column of the last cell that contains the hyperlink
|
||||
*/
|
||||
public void setLastColumn(int col){
|
||||
record.setLastColumn((short)col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hypelink address. Depending on the hyperlink type it can be URL, e-mail, patrh to a file, etc.
|
||||
*
|
||||
* @return the address of this hyperlink
|
||||
*/
|
||||
public String getAddress(){
|
||||
return record.getAddress();
|
||||
}
|
||||
public String getTextMark(){
|
||||
return record.getTextMark();
|
||||
}
|
||||
public void setTextMark(String textMark) {
|
||||
record.setTextMark(textMark);
|
||||
}
|
||||
public String getShortFilename(){
|
||||
return record.getShortFilename();
|
||||
}
|
||||
public void setShortFilename(String shortFilename) {
|
||||
record.setShortFilename(shortFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hypelink address. Depending on the hyperlink type it can be URL, e-mail, patrh to a file, etc.
|
||||
*
|
||||
* @param address the address of this hyperlink
|
||||
*/
|
||||
public void setAddress(String address){
|
||||
record.setAddress(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return text label for this hyperlink
|
||||
*
|
||||
* @return text to display
|
||||
*/
|
||||
public String getLabel(){
|
||||
return record.getLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets text label for this hyperlink
|
||||
*
|
||||
* @param label text label for this hyperlink
|
||||
*/
|
||||
public void setLabel(String label){
|
||||
record.setLabel(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of this hyperlink
|
||||
*
|
||||
* @return the type of this hyperlink
|
||||
*/
|
||||
public int getType(){
|
||||
return link_type;
|
||||
}
|
||||
}
|
||||
|
@ -1,194 +1,193 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.model.Sheet;
|
||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
|
||||
import org.apache.poi.ss.util.Region;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
|
||||
/**
|
||||
* The 'Conditional Formatting' facet of <tt>HSSFSheet</tt>
|
||||
*
|
||||
* @author Dmitriy Kumshayev
|
||||
*/
|
||||
public final class HSSFSheetConditionalFormatting {
|
||||
|
||||
private final HSSFSheet _sheet;
|
||||
private final ConditionalFormattingTable _conditionalFormattingTable;
|
||||
|
||||
/* package */ HSSFSheetConditionalFormatting(HSSFSheet sheet) {
|
||||
_sheet = sheet;
|
||||
_conditionalFormattingTable = sheet.getSheet().getConditionalFormattingTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method allowing to create a conditional formatting rule
|
||||
* with a cell comparison operator<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
*
|
||||
* @param comparisonOperation - a constant value from
|
||||
* <tt>{@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator}</tt>: <p>
|
||||
* <ul>
|
||||
* <li>BETWEEN</li>
|
||||
* <li>NOT_BETWEEN</li>
|
||||
* <li>EQUAL</li>
|
||||
* <li>NOT_EQUAL</li>
|
||||
* <li>GT</li>
|
||||
* <li>LT</li>
|
||||
* <li>GE</li>
|
||||
* <li>LE</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* @param formula1 - formula for the valued, compared with the cell
|
||||
* @param formula2 - second formula (only used with
|
||||
* {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#BETWEEN}) and
|
||||
* {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#NOT_BETWEEN} operations)
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(
|
||||
byte comparisonOperation,
|
||||
String formula1,
|
||||
String formula2) {
|
||||
|
||||
HSSFWorkbook wb = _sheet.getWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, formula2);
|
||||
return new HSSFConditionalFormattingRule(wb, rr);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method allowing to create a conditional formatting rule with a formula.<br>
|
||||
*
|
||||
* The formatting rules are applied by Excel when the value of the formula not equal to 0.<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
* @param formula - formula for the valued, compared with the cell
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {
|
||||
HSSFWorkbook wb = _sheet.getWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, formula);
|
||||
return new HSSFConditionalFormattingRule(wb, rr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a copy of HSSFConditionalFormatting object to the sheet
|
||||
* <p>This method could be used to copy HSSFConditionalFormatting object
|
||||
* from one sheet to another. For example:
|
||||
* <pre>
|
||||
* HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
|
||||
* newSheet.addConditionalFormatting(cf);
|
||||
* </pre>
|
||||
*
|
||||
* @param cf HSSFConditionalFormatting object
|
||||
* @return index of the new Conditional Formatting object
|
||||
*/
|
||||
public int addConditionalFormatting( HSSFConditionalFormatting cf ) {
|
||||
CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
|
||||
|
||||
return _conditionalFormattingTable.add(cfraClone);
|
||||
}
|
||||
/**
|
||||
* @deprecated use <tt>CellRangeAddress</tt> instead of <tt>Region</tt>
|
||||
*/
|
||||
public int addConditionalFormatting(Region[] regions, HSSFConditionalFormattingRule[] cfRules) {
|
||||
return addConditionalFormatting(Region.convertRegionsToCellRanges(regions), cfRules);
|
||||
}
|
||||
/**
|
||||
* Allows to add a new Conditional Formatting set to the sheet.
|
||||
*
|
||||
* @param regions - list of rectangular regions to apply conditional formatting rules
|
||||
* @param cfRules - set of up to three conditional formatting rules
|
||||
*
|
||||
* @return index of the newly created Conditional Formatting object
|
||||
*/
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions, HSSFConditionalFormattingRule[] cfRules) {
|
||||
if (regions == null) {
|
||||
throw new IllegalArgumentException("regions must not be null");
|
||||
}
|
||||
for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL97);
|
||||
|
||||
if (cfRules == null) {
|
||||
throw new IllegalArgumentException("cfRules must not be null");
|
||||
}
|
||||
if (cfRules.length == 0) {
|
||||
throw new IllegalArgumentException("cfRules must not be empty");
|
||||
}
|
||||
if (cfRules.length > 3) {
|
||||
throw new IllegalArgumentException("Number of rules must not exceed 3");
|
||||
}
|
||||
|
||||
CFRuleRecord[] rules = new CFRuleRecord[cfRules.length];
|
||||
for (int i = 0; i != cfRules.length; i++) {
|
||||
rules[i] = cfRules[i].getCfRuleRecord();
|
||||
}
|
||||
CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules);
|
||||
return _conditionalFormattingTable.add(cfra);
|
||||
}
|
||||
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
HSSFConditionalFormattingRule rule1)
|
||||
{
|
||||
return addConditionalFormatting(regions,
|
||||
new HSSFConditionalFormattingRule[]
|
||||
{
|
||||
rule1
|
||||
});
|
||||
}
|
||||
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
HSSFConditionalFormattingRule rule1,
|
||||
HSSFConditionalFormattingRule rule2)
|
||||
{
|
||||
return addConditionalFormatting(regions,
|
||||
new HSSFConditionalFormattingRule[]
|
||||
{
|
||||
rule1, rule2
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* gets Conditional Formatting object at a particular index
|
||||
*
|
||||
* @param index
|
||||
* of the Conditional Formatting object to fetch
|
||||
* @return Conditional Formatting object
|
||||
*/
|
||||
public HSSFConditionalFormatting getConditionalFormattingAt(int index) {
|
||||
CFRecordsAggregate cf = _conditionalFormattingTable.get(index);
|
||||
if (cf == null) {
|
||||
return null;
|
||||
}
|
||||
return new HSSFConditionalFormatting(_sheet.getWorkbook(), cf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return number of Conditional Formatting objects of the sheet
|
||||
*/
|
||||
public int getNumConditionalFormattings() {
|
||||
return _conditionalFormattingTable.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a Conditional Formatting object by index
|
||||
* @param index of a Conditional Formatting object to remove
|
||||
*/
|
||||
public void removeConditionalFormatting(int index) {
|
||||
_conditionalFormattingTable.remove(index);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
|
||||
import org.apache.poi.ss.util.Region;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
|
||||
/**
|
||||
* The 'Conditional Formatting' facet of <tt>HSSFSheet</tt>
|
||||
*
|
||||
* @author Dmitriy Kumshayev
|
||||
*/
|
||||
public final class HSSFSheetConditionalFormatting {
|
||||
|
||||
private final HSSFSheet _sheet;
|
||||
private final ConditionalFormattingTable _conditionalFormattingTable;
|
||||
|
||||
/* package */ HSSFSheetConditionalFormatting(HSSFSheet sheet) {
|
||||
_sheet = sheet;
|
||||
_conditionalFormattingTable = sheet.getSheet().getConditionalFormattingTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method allowing to create a conditional formatting rule
|
||||
* with a cell comparison operator<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
*
|
||||
* @param comparisonOperation - a constant value from
|
||||
* <tt>{@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator}</tt>: <p>
|
||||
* <ul>
|
||||
* <li>BETWEEN</li>
|
||||
* <li>NOT_BETWEEN</li>
|
||||
* <li>EQUAL</li>
|
||||
* <li>NOT_EQUAL</li>
|
||||
* <li>GT</li>
|
||||
* <li>LT</li>
|
||||
* <li>GE</li>
|
||||
* <li>LE</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* @param formula1 - formula for the valued, compared with the cell
|
||||
* @param formula2 - second formula (only used with
|
||||
* {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#BETWEEN}) and
|
||||
* {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#NOT_BETWEEN} operations)
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(
|
||||
byte comparisonOperation,
|
||||
String formula1,
|
||||
String formula2) {
|
||||
|
||||
HSSFWorkbook wb = _sheet.getWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, formula2);
|
||||
return new HSSFConditionalFormattingRule(wb, rr);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method allowing to create a conditional formatting rule with a formula.<br>
|
||||
*
|
||||
* The formatting rules are applied by Excel when the value of the formula not equal to 0.<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
* @param formula - formula for the valued, compared with the cell
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {
|
||||
HSSFWorkbook wb = _sheet.getWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, formula);
|
||||
return new HSSFConditionalFormattingRule(wb, rr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a copy of HSSFConditionalFormatting object to the sheet
|
||||
* <p>This method could be used to copy HSSFConditionalFormatting object
|
||||
* from one sheet to another. For example:
|
||||
* <pre>
|
||||
* HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
|
||||
* newSheet.addConditionalFormatting(cf);
|
||||
* </pre>
|
||||
*
|
||||
* @param cf HSSFConditionalFormatting object
|
||||
* @return index of the new Conditional Formatting object
|
||||
*/
|
||||
public int addConditionalFormatting( HSSFConditionalFormatting cf ) {
|
||||
CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
|
||||
|
||||
return _conditionalFormattingTable.add(cfraClone);
|
||||
}
|
||||
/**
|
||||
* @deprecated use <tt>CellRangeAddress</tt> instead of <tt>Region</tt>
|
||||
*/
|
||||
public int addConditionalFormatting(Region[] regions, HSSFConditionalFormattingRule[] cfRules) {
|
||||
return addConditionalFormatting(Region.convertRegionsToCellRanges(regions), cfRules);
|
||||
}
|
||||
/**
|
||||
* Allows to add a new Conditional Formatting set to the sheet.
|
||||
*
|
||||
* @param regions - list of rectangular regions to apply conditional formatting rules
|
||||
* @param cfRules - set of up to three conditional formatting rules
|
||||
*
|
||||
* @return index of the newly created Conditional Formatting object
|
||||
*/
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions, HSSFConditionalFormattingRule[] cfRules) {
|
||||
if (regions == null) {
|
||||
throw new IllegalArgumentException("regions must not be null");
|
||||
}
|
||||
for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL97);
|
||||
|
||||
if (cfRules == null) {
|
||||
throw new IllegalArgumentException("cfRules must not be null");
|
||||
}
|
||||
if (cfRules.length == 0) {
|
||||
throw new IllegalArgumentException("cfRules must not be empty");
|
||||
}
|
||||
if (cfRules.length > 3) {
|
||||
throw new IllegalArgumentException("Number of rules must not exceed 3");
|
||||
}
|
||||
|
||||
CFRuleRecord[] rules = new CFRuleRecord[cfRules.length];
|
||||
for (int i = 0; i != cfRules.length; i++) {
|
||||
rules[i] = cfRules[i].getCfRuleRecord();
|
||||
}
|
||||
CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules);
|
||||
return _conditionalFormattingTable.add(cfra);
|
||||
}
|
||||
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
HSSFConditionalFormattingRule rule1)
|
||||
{
|
||||
return addConditionalFormatting(regions,
|
||||
new HSSFConditionalFormattingRule[]
|
||||
{
|
||||
rule1
|
||||
});
|
||||
}
|
||||
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
HSSFConditionalFormattingRule rule1,
|
||||
HSSFConditionalFormattingRule rule2)
|
||||
{
|
||||
return addConditionalFormatting(regions,
|
||||
new HSSFConditionalFormattingRule[]
|
||||
{
|
||||
rule1, rule2
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* gets Conditional Formatting object at a particular index
|
||||
*
|
||||
* @param index
|
||||
* of the Conditional Formatting object to fetch
|
||||
* @return Conditional Formatting object
|
||||
*/
|
||||
public HSSFConditionalFormatting getConditionalFormattingAt(int index) {
|
||||
CFRecordsAggregate cf = _conditionalFormattingTable.get(index);
|
||||
if (cf == null) {
|
||||
return null;
|
||||
}
|
||||
return new HSSFConditionalFormatting(_sheet.getWorkbook(), cf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return number of Conditional Formatting objects of the sheet
|
||||
*/
|
||||
public int getNumConditionalFormattings() {
|
||||
return _conditionalFormattingTable.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a Conditional Formatting object by index
|
||||
* @param index of a Conditional Formatting object to remove
|
||||
*/
|
||||
public void removeConditionalFormatting(int index) {
|
||||
_conditionalFormattingTable.remove(index);
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +1,38 @@
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.record.SelectionRecord;
|
||||
|
||||
/**
|
||||
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
|
||||
*
|
||||
* Note - {@link SelectionRecord} uses the BIFF5 version of this structure
|
||||
* @deprecated use {@link org.apache.poi.ss.util.CellRangeAddress}
|
||||
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
|
||||
*/
|
||||
public class CellRangeAddress extends org.apache.poi.ss.util.CellRangeAddress {
|
||||
|
||||
public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
super(firstRow, lastRow, firstCol, lastCol);
|
||||
}
|
||||
public CellRangeAddress(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.record.SelectionRecord;
|
||||
|
||||
/**
|
||||
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
|
||||
*
|
||||
* Note - {@link SelectionRecord} uses the BIFF5 version of this structure
|
||||
* @deprecated use {@link org.apache.poi.ss.util.CellRangeAddress}
|
||||
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
|
||||
*/
|
||||
public class CellRangeAddress extends org.apache.poi.ss.util.CellRangeAddress {
|
||||
|
||||
public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
super(firstRow, lastRow, firstCol, lastCol);
|
||||
}
|
||||
public CellRangeAddress(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
}
|
||||
|
@ -1,73 +1,73 @@
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
|
||||
import org.apache.poi.ss.util.CellRangeAddressBase;
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
|
||||
*
|
||||
* Like {@link CellRangeAddress} except column fields are 8-bit.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class CellRangeAddress8Bit extends CellRangeAddressBase {
|
||||
|
||||
public static final int ENCODED_SIZE = 6;
|
||||
|
||||
public CellRangeAddress8Bit(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
super(firstRow, lastRow, firstCol, lastCol);
|
||||
}
|
||||
|
||||
public CellRangeAddress8Bit(LittleEndianInput in) {
|
||||
super(readUShortAndCheck(in), in.readUShort(), in.readUByte(), in.readUByte());
|
||||
}
|
||||
|
||||
private static int readUShortAndCheck(LittleEndianInput in) {
|
||||
if (in.available() < ENCODED_SIZE) {
|
||||
// Ran out of data
|
||||
throw new RuntimeException("Ran out of data reading CellRangeAddress");
|
||||
}
|
||||
return in.readUShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #serialize(LittleEndianOutput)}
|
||||
*/
|
||||
public int serialize(int offset, byte[] data) {
|
||||
serialize(new LittleEndianByteArrayOutputStream(data, offset, ENCODED_SIZE));
|
||||
return ENCODED_SIZE;
|
||||
}
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(getFirstRow());
|
||||
out.writeShort(getLastRow());
|
||||
out.writeByte(getFirstColumn());
|
||||
out.writeByte(getLastColumn());
|
||||
}
|
||||
|
||||
public CellRangeAddress8Bit copy() {
|
||||
return new CellRangeAddress8Bit(getFirstRow(), getLastRow(), getFirstColumn(), getLastColumn());
|
||||
}
|
||||
|
||||
public static int getEncodedSize(int numberOfItems) {
|
||||
return numberOfItems * ENCODED_SIZE;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
|
||||
import org.apache.poi.ss.util.CellRangeAddressBase;
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
|
||||
*
|
||||
* Like {@link CellRangeAddress} except column fields are 8-bit.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class CellRangeAddress8Bit extends CellRangeAddressBase {
|
||||
|
||||
public static final int ENCODED_SIZE = 6;
|
||||
|
||||
public CellRangeAddress8Bit(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
super(firstRow, lastRow, firstCol, lastCol);
|
||||
}
|
||||
|
||||
public CellRangeAddress8Bit(LittleEndianInput in) {
|
||||
super(readUShortAndCheck(in), in.readUShort(), in.readUByte(), in.readUByte());
|
||||
}
|
||||
|
||||
private static int readUShortAndCheck(LittleEndianInput in) {
|
||||
if (in.available() < ENCODED_SIZE) {
|
||||
// Ran out of data
|
||||
throw new RuntimeException("Ran out of data reading CellRangeAddress");
|
||||
}
|
||||
return in.readUShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #serialize(LittleEndianOutput)}
|
||||
*/
|
||||
public int serialize(int offset, byte[] data) {
|
||||
serialize(new LittleEndianByteArrayOutputStream(data, offset, ENCODED_SIZE));
|
||||
return ENCODED_SIZE;
|
||||
}
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(getFirstRow());
|
||||
out.writeShort(getLastRow());
|
||||
out.writeByte(getFirstColumn());
|
||||
out.writeByte(getLastColumn());
|
||||
}
|
||||
|
||||
public CellRangeAddress8Bit copy() {
|
||||
return new CellRangeAddress8Bit(getFirstRow(), getLastRow(), getFirstColumn(), getLastColumn());
|
||||
}
|
||||
|
||||
public static int getEncodedSize(int numberOfItems) {
|
||||
return numberOfItems * ENCODED_SIZE;
|
||||
}
|
||||
}
|
||||
|
@ -1,74 +1,74 @@
|
||||
/* ====================================================================
|
||||
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.poifs.dev;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.*;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* Dump internal structure of a OLE2 file into file system
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class POIFSDump {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
System.out.println("Dumping " + args[i]);
|
||||
FileInputStream is = new FileInputStream(args[i]);
|
||||
POIFSFileSystem fs = new POIFSFileSystem(is);
|
||||
is.close();
|
||||
|
||||
DirectoryEntry root = fs.getRoot();
|
||||
File file = new File(root.getName());
|
||||
file.mkdir();
|
||||
|
||||
dump(root, file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void dump(DirectoryEntry root, File parent) throws IOException {
|
||||
for(Iterator it = root.getEntries(); it.hasNext();){
|
||||
Entry entry = (Entry)it.next();
|
||||
if(entry instanceof DocumentNode){
|
||||
DocumentNode node = (DocumentNode)entry;
|
||||
DocumentInputStream is = new DocumentInputStream(node);
|
||||
byte[] bytes = new byte[node.getSize()];
|
||||
is.read(bytes);
|
||||
is.close();
|
||||
|
||||
FileOutputStream out = new FileOutputStream(new File(parent, node.getName().trim()));
|
||||
out.write(bytes);
|
||||
out.close();
|
||||
} else if (entry instanceof DirectoryEntry){
|
||||
DirectoryEntry dir = (DirectoryEntry)entry;
|
||||
File file = new File(parent, entry.getName());
|
||||
file.mkdir();
|
||||
dump(dir, file);
|
||||
} else {
|
||||
System.err.println("Skipping unsupported POIFS entry: " + entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
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.poifs.dev;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.*;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* Dump internal structure of a OLE2 file into file system
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class POIFSDump {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
System.out.println("Dumping " + args[i]);
|
||||
FileInputStream is = new FileInputStream(args[i]);
|
||||
POIFSFileSystem fs = new POIFSFileSystem(is);
|
||||
is.close();
|
||||
|
||||
DirectoryEntry root = fs.getRoot();
|
||||
File file = new File(root.getName());
|
||||
file.mkdir();
|
||||
|
||||
dump(root, file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void dump(DirectoryEntry root, File parent) throws IOException {
|
||||
for(Iterator it = root.getEntries(); it.hasNext();){
|
||||
Entry entry = (Entry)it.next();
|
||||
if(entry instanceof DocumentNode){
|
||||
DocumentNode node = (DocumentNode)entry;
|
||||
DocumentInputStream is = new DocumentInputStream(node);
|
||||
byte[] bytes = new byte[node.getSize()];
|
||||
is.read(bytes);
|
||||
is.close();
|
||||
|
||||
FileOutputStream out = new FileOutputStream(new File(parent, node.getName().trim()));
|
||||
out.write(bytes);
|
||||
out.close();
|
||||
} else if (entry instanceof DirectoryEntry){
|
||||
DirectoryEntry dir = (DirectoryEntry)entry;
|
||||
File file = new File(parent, entry.getName());
|
||||
file.mkdir();
|
||||
dump(dir, file);
|
||||
} else {
|
||||
System.err.println("Skipping unsupported POIFS entry: " + entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,120 +1,119 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss;
|
||||
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
|
||||
/**
|
||||
* This enum allows spreadsheets from multiple Excel versions to be handled by the common code.
|
||||
* Properties of this enum correspond to attributes of the <i>spreadsheet</i> that are easily
|
||||
* discernable to the user. It is not intended to deal with low-level issues like file formats.
|
||||
* <p/>
|
||||
*
|
||||
* @author Josh Micich
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public enum SpreadsheetVersion {
|
||||
/**
|
||||
* Excel97 format aka BIFF8
|
||||
* <ul>
|
||||
* <li>The total number of available columns is 256 (2^8)</li>
|
||||
* <li>The total number of available rows is 64k (2^16)</li>
|
||||
* <li>The maximum number of arguments to a function is 30</li>
|
||||
* <li>Number of conditional format conditions on a cell is 3</li>
|
||||
* </ul>
|
||||
*/
|
||||
EXCEL97(0x10000, 0x0100, 30, 3),
|
||||
|
||||
/**
|
||||
* Excel2007
|
||||
*
|
||||
* <ul>
|
||||
* <li>The total number of available columns is 16K (2^14)</li>
|
||||
* <li>The total number of available rows is 1M (2^20)</li>
|
||||
* <li>The maximum number of arguments to a function is 255</li>
|
||||
* <li>Number of conditional format conditions on a cell is unlimited
|
||||
* (actually limited by available memory in Excel)</li>
|
||||
* <ul>
|
||||
*/
|
||||
EXCEL2007(0x100000, 0x4000, 255, Integer.MAX_VALUE);
|
||||
|
||||
private final int _maxRows;
|
||||
private final int _maxColumns;
|
||||
private final int _maxFunctionArgs;
|
||||
private final int _maxCondFormats;
|
||||
|
||||
private SpreadsheetVersion(int maxRows, int maxColumns, int maxFunctionArgs, int maxCondFormats) {
|
||||
_maxRows = maxRows;
|
||||
_maxColumns = maxColumns;
|
||||
_maxFunctionArgs = maxFunctionArgs;
|
||||
_maxCondFormats = maxCondFormats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum number of usable rows in each spreadsheet
|
||||
*/
|
||||
public int getMaxRows() {
|
||||
return _maxRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the last (maximum) valid row index, equals to <code> getMaxRows() - 1 </code>
|
||||
*/
|
||||
public int getLastRowIndex() {
|
||||
return _maxRows - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum number of usable columns in each spreadsheet
|
||||
*/
|
||||
public int getMaxColumns() {
|
||||
return _maxColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the last (maximum) valid column index, equals to <code> getMaxColumns() - 1 </code>
|
||||
*/
|
||||
public int getLastColumnIndex() {
|
||||
return _maxColumns - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum number arguments that can be passed to a multi-arg
|
||||
* function (e.g. COUNTIF)
|
||||
*/
|
||||
public int getMaxFunctionArgs() {
|
||||
return _maxFunctionArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the maximum number of conditional format conditions on a cell
|
||||
*/
|
||||
public int getMaxConditionalFormats() {
|
||||
return _maxCondFormats;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the last valid column index in a ALPHA-26 representation
|
||||
* ( <code>IV</code> or <code>XFD</code>).
|
||||
*/
|
||||
public String getLastColumnName() {
|
||||
return CellReference.convertNumToColString(getLastColumnIndex());
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss;
|
||||
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
|
||||
/**
|
||||
* This enum allows spreadsheets from multiple Excel versions to be handled by the common code.
|
||||
* Properties of this enum correspond to attributes of the <i>spreadsheet</i> that are easily
|
||||
* discernable to the user. It is not intended to deal with low-level issues like file formats.
|
||||
* <p/>
|
||||
*
|
||||
* @author Josh Micich
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public enum SpreadsheetVersion {
|
||||
/**
|
||||
* Excel97 format aka BIFF8
|
||||
* <ul>
|
||||
* <li>The total number of available columns is 256 (2^8)</li>
|
||||
* <li>The total number of available rows is 64k (2^16)</li>
|
||||
* <li>The maximum number of arguments to a function is 30</li>
|
||||
* <li>Number of conditional format conditions on a cell is 3</li>
|
||||
* </ul>
|
||||
*/
|
||||
EXCEL97(0x10000, 0x0100, 30, 3),
|
||||
|
||||
/**
|
||||
* Excel2007
|
||||
*
|
||||
* <ul>
|
||||
* <li>The total number of available columns is 16K (2^14)</li>
|
||||
* <li>The total number of available rows is 1M (2^20)</li>
|
||||
* <li>The maximum number of arguments to a function is 255</li>
|
||||
* <li>Number of conditional format conditions on a cell is unlimited
|
||||
* (actually limited by available memory in Excel)</li>
|
||||
* <ul>
|
||||
*/
|
||||
EXCEL2007(0x100000, 0x4000, 255, Integer.MAX_VALUE);
|
||||
|
||||
private final int _maxRows;
|
||||
private final int _maxColumns;
|
||||
private final int _maxFunctionArgs;
|
||||
private final int _maxCondFormats;
|
||||
|
||||
private SpreadsheetVersion(int maxRows, int maxColumns, int maxFunctionArgs, int maxCondFormats) {
|
||||
_maxRows = maxRows;
|
||||
_maxColumns = maxColumns;
|
||||
_maxFunctionArgs = maxFunctionArgs;
|
||||
_maxCondFormats = maxCondFormats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum number of usable rows in each spreadsheet
|
||||
*/
|
||||
public int getMaxRows() {
|
||||
return _maxRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the last (maximum) valid row index, equals to <code> getMaxRows() - 1 </code>
|
||||
*/
|
||||
public int getLastRowIndex() {
|
||||
return _maxRows - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum number of usable columns in each spreadsheet
|
||||
*/
|
||||
public int getMaxColumns() {
|
||||
return _maxColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the last (maximum) valid column index, equals to <code> getMaxColumns() - 1 </code>
|
||||
*/
|
||||
public int getLastColumnIndex() {
|
||||
return _maxColumns - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum number arguments that can be passed to a multi-arg function (e.g. COUNTIF)
|
||||
*/
|
||||
public int getMaxFunctionArgs() {
|
||||
return _maxFunctionArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the maximum number of conditional format conditions on a cell
|
||||
*/
|
||||
public int getMaxConditionalFormats() {
|
||||
return _maxCondFormats;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the last valid column index in a ALPHA-26 representation
|
||||
* (<code>IV</code> or <code>XFD</code>).
|
||||
*/
|
||||
public String getLastColumnName() {
|
||||
return CellReference.convertNumToColString(getLastColumnIndex());
|
||||
}
|
||||
}
|
||||
|
@ -1,77 +1,77 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* Stores details about the current evaluation of a cell.<br/>
|
||||
*/
|
||||
final class CellEvaluationFrame {
|
||||
|
||||
private final FormulaCellCacheEntry _cce;
|
||||
private final Set<CellCacheEntry> _sensitiveInputCells;
|
||||
private FormulaUsedBlankCellSet _usedBlankCellGroup;
|
||||
|
||||
public CellEvaluationFrame(FormulaCellCacheEntry cce) {
|
||||
_cce = cce;
|
||||
_sensitiveInputCells = new HashSet<CellCacheEntry>();
|
||||
}
|
||||
public CellCacheEntry getCCE() {
|
||||
return _cce;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
/**
|
||||
* @param inputCell a cell directly used by the formula of this evaluation frame
|
||||
*/
|
||||
public void addSensitiveInputCell(CellCacheEntry inputCell) {
|
||||
_sensitiveInputCells.add(inputCell);
|
||||
}
|
||||
/**
|
||||
* @return never <code>null</code>, (possibly empty) array of all cells directly used while
|
||||
* evaluating the formula of this frame.
|
||||
*/
|
||||
private CellCacheEntry[] getSensitiveInputCells() {
|
||||
int nItems = _sensitiveInputCells.size();
|
||||
if (nItems < 1) {
|
||||
return CellCacheEntry.EMPTY_ARRAY;
|
||||
}
|
||||
CellCacheEntry[] result = new CellCacheEntry[nItems];
|
||||
_sensitiveInputCells.toArray(result);
|
||||
return result;
|
||||
}
|
||||
public void addUsedBlankCell(int bookIndex, int sheetIndex, int rowIndex, int columnIndex) {
|
||||
if (_usedBlankCellGroup == null) {
|
||||
_usedBlankCellGroup = new FormulaUsedBlankCellSet();
|
||||
}
|
||||
_usedBlankCellGroup.addCell(bookIndex, sheetIndex, rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
public void updateFormulaResult(ValueEval result) {
|
||||
_cce.updateFormulaResult(result, getSensitiveInputCells(), _usedBlankCellGroup);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* Stores details about the current evaluation of a cell.<br/>
|
||||
*/
|
||||
final class CellEvaluationFrame {
|
||||
|
||||
private final FormulaCellCacheEntry _cce;
|
||||
private final Set<CellCacheEntry> _sensitiveInputCells;
|
||||
private FormulaUsedBlankCellSet _usedBlankCellGroup;
|
||||
|
||||
public CellEvaluationFrame(FormulaCellCacheEntry cce) {
|
||||
_cce = cce;
|
||||
_sensitiveInputCells = new HashSet<CellCacheEntry>();
|
||||
}
|
||||
public CellCacheEntry getCCE() {
|
||||
return _cce;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
/**
|
||||
* @param inputCell a cell directly used by the formula of this evaluation frame
|
||||
*/
|
||||
public void addSensitiveInputCell(CellCacheEntry inputCell) {
|
||||
_sensitiveInputCells.add(inputCell);
|
||||
}
|
||||
/**
|
||||
* @return never <code>null</code>, (possibly empty) array of all cells directly used while
|
||||
* evaluating the formula of this frame.
|
||||
*/
|
||||
private CellCacheEntry[] getSensitiveInputCells() {
|
||||
int nItems = _sensitiveInputCells.size();
|
||||
if (nItems < 1) {
|
||||
return CellCacheEntry.EMPTY_ARRAY;
|
||||
}
|
||||
CellCacheEntry[] result = new CellCacheEntry[nItems];
|
||||
_sensitiveInputCells.toArray(result);
|
||||
return result;
|
||||
}
|
||||
public void addUsedBlankCell(int bookIndex, int sheetIndex, int rowIndex, int columnIndex) {
|
||||
if (_usedBlankCellGroup == null) {
|
||||
_usedBlankCellGroup = new FormulaUsedBlankCellSet();
|
||||
}
|
||||
_usedBlankCellGroup.addCell(bookIndex, sheetIndex, rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
public void updateFormulaResult(ValueEval result) {
|
||||
_cce.updateFormulaResult(result, getSensitiveInputCells(), _usedBlankCellGroup);
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +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.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
/**
|
||||
* Abstracts a name record for formula evaluation.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface EvaluationName {
|
||||
|
||||
String getNameText();
|
||||
|
||||
boolean isFunctionName();
|
||||
|
||||
boolean hasFormula();
|
||||
|
||||
Ptg[] getNameDefinition();
|
||||
|
||||
boolean isRange();
|
||||
NamePtg createPtg();
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
/**
|
||||
* Abstracts a name record for formula evaluation.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface EvaluationName {
|
||||
|
||||
String getNameText();
|
||||
|
||||
boolean isFunctionName();
|
||||
|
||||
boolean hasFormula();
|
||||
|
||||
Ptg[] getNameDefinition();
|
||||
|
||||
boolean isRange();
|
||||
NamePtg createPtg();
|
||||
}
|
||||
|
@ -1,65 +1,65 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
|
||||
/**
|
||||
* Abstracts a workbook for the purpose of formula evaluation.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface EvaluationWorkbook {
|
||||
String getSheetName(int sheetIndex);
|
||||
/**
|
||||
* @return -1 if the specified sheet is from a different book
|
||||
*/
|
||||
int getSheetIndex(EvaluationSheet sheet);
|
||||
int getSheetIndex(String sheetName);
|
||||
|
||||
EvaluationSheet getSheet(int sheetIndex);
|
||||
|
||||
/**
|
||||
* @return <code>null</code> if externSheetIndex refers to a sheet inside the current workbook
|
||||
*/
|
||||
ExternalSheet getExternalSheet(int externSheetIndex);
|
||||
int convertFromExternSheetIndex(int externSheetIndex);
|
||||
EvaluationName getName(NamePtg namePtg);
|
||||
String resolveNameXText(NameXPtg ptg);
|
||||
Ptg[] getFormulaTokens(EvaluationCell cell);
|
||||
|
||||
class ExternalSheet {
|
||||
private final String _workbookName;
|
||||
private final String _sheetName;
|
||||
|
||||
public ExternalSheet(String workbookName, String sheetName) {
|
||||
_workbookName = workbookName;
|
||||
_sheetName = sheetName;
|
||||
}
|
||||
public String getWorkbookName() {
|
||||
return _workbookName;
|
||||
}
|
||||
public String getSheetName() {
|
||||
return _sheetName;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
|
||||
/**
|
||||
* Abstracts a workbook for the purpose of formula evaluation.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface EvaluationWorkbook {
|
||||
String getSheetName(int sheetIndex);
|
||||
/**
|
||||
* @return -1 if the specified sheet is from a different book
|
||||
*/
|
||||
int getSheetIndex(EvaluationSheet sheet);
|
||||
int getSheetIndex(String sheetName);
|
||||
|
||||
EvaluationSheet getSheet(int sheetIndex);
|
||||
|
||||
/**
|
||||
* @return <code>null</code> if externSheetIndex refers to a sheet inside the current workbook
|
||||
*/
|
||||
ExternalSheet getExternalSheet(int externSheetIndex);
|
||||
int convertFromExternSheetIndex(int externSheetIndex);
|
||||
EvaluationName getName(NamePtg namePtg);
|
||||
String resolveNameXText(NameXPtg ptg);
|
||||
Ptg[] getFormulaTokens(EvaluationCell cell);
|
||||
|
||||
class ExternalSheet {
|
||||
private final String _workbookName;
|
||||
private final String _sheetName;
|
||||
|
||||
public ExternalSheet(String workbookName, String sheetName) {
|
||||
_workbookName = workbookName;
|
||||
_sheetName = sheetName;
|
||||
}
|
||||
public String getWorkbookName() {
|
||||
return _workbookName;
|
||||
}
|
||||
public String getSheetName() {
|
||||
return _sheetName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,197 +1,197 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.hssf.record.ArrayRecord;
|
||||
import org.apache.poi.hssf.record.SharedFormulaRecord;
|
||||
import org.apache.poi.hssf.record.TableRecord;
|
||||
import org.apache.poi.hssf.record.formula.ExpPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.TblPtg;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Encapsulates an encoded formula token array.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class Formula {
|
||||
|
||||
private static final Formula EMPTY = new Formula(new byte[0], 0);
|
||||
|
||||
/** immutable */
|
||||
private final byte[] _byteEncoding;
|
||||
private final int _encodedTokenLen;
|
||||
|
||||
private Formula(byte[] byteEncoding, int encodedTokenLen) {
|
||||
_byteEncoding = byteEncoding;
|
||||
_encodedTokenLen = encodedTokenLen;
|
||||
if (false) { // set to true to eagerly check Ptg decoding
|
||||
LittleEndianByteArrayInputStream in = new LittleEndianByteArrayInputStream(byteEncoding);
|
||||
Ptg.readTokens(encodedTokenLen, in);
|
||||
int nUnusedBytes = _byteEncoding.length - in.getReadIndex();
|
||||
if (nUnusedBytes > 0) {
|
||||
// TODO - this seems to occur when IntersectionPtg is present
|
||||
// This example file "IntersectionPtg.xls"
|
||||
// used by test: TestIntersectionPtg.testReading()
|
||||
// has 10 bytes unused at the end of the formula
|
||||
// 10 extra bytes are just 0x01 and 0x00
|
||||
System.out.println(nUnusedBytes + " unused bytes at end of formula");
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Convenience method for {@link #read(int, LittleEndianInput, int)}
|
||||
*/
|
||||
public static Formula read(int encodedTokenLen, LittleEndianInput in) {
|
||||
return read(encodedTokenLen, in, encodedTokenLen);
|
||||
}
|
||||
/**
|
||||
* When there are no array constants present, <tt>encodedTokenLen</tt>==<tt>totalEncodedLen</tt>
|
||||
* @param encodedTokenLen number of bytes in the stream taken by the plain formula tokens
|
||||
* @param totalEncodedLen the total number of bytes in the formula (includes trailing encoding
|
||||
* for array constants, but does not include 2 bytes for initial <tt>ushort encodedTokenLen</tt> field.
|
||||
* @return A new formula object as read from the stream. Possibly empty, never <code>null</code>.
|
||||
*/
|
||||
public static Formula read(int encodedTokenLen, LittleEndianInput in, int totalEncodedLen) {
|
||||
byte[] byteEncoding = new byte[totalEncodedLen];
|
||||
in.readFully(byteEncoding);
|
||||
return new Formula(byteEncoding, encodedTokenLen);
|
||||
}
|
||||
|
||||
public Ptg[] getTokens() {
|
||||
LittleEndianInput in = new LittleEndianByteArrayInputStream(_byteEncoding);
|
||||
return Ptg.readTokens(_encodedTokenLen, in);
|
||||
}
|
||||
/**
|
||||
* Writes The formula encoding is includes:
|
||||
* <ul>
|
||||
* <li>ushort tokenDataLen</li>
|
||||
* <li>tokenData</li>
|
||||
* <li>arrayConstantData (if present)</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(_encodedTokenLen);
|
||||
out.write(_byteEncoding);
|
||||
}
|
||||
|
||||
public void serializeTokens(LittleEndianOutput out) {
|
||||
out.write(_byteEncoding, 0, _encodedTokenLen);
|
||||
}
|
||||
public void serializeArrayConstantData(LittleEndianOutput out) {
|
||||
int len = _byteEncoding.length-_encodedTokenLen;
|
||||
out.write(_byteEncoding, _encodedTokenLen, len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return total formula encoding length. The formula encoding includes:
|
||||
* <ul>
|
||||
* <li>ushort tokenDataLen</li>
|
||||
* <li>tokenData</li>
|
||||
* <li>arrayConstantData (optional)</li>
|
||||
* </ul>
|
||||
* Note - this value is different to <tt>tokenDataLength</tt>
|
||||
*/
|
||||
public int getEncodedSize() {
|
||||
return 2 + _byteEncoding.length;
|
||||
}
|
||||
/**
|
||||
* This method is often used when the formula length does not appear immediately before
|
||||
* the encoded token data.
|
||||
*
|
||||
* @return the encoded length of the plain formula tokens. This does <em>not</em> include
|
||||
* the leading ushort field, nor any trailing array constant data.
|
||||
*/
|
||||
public int getEncodedTokenSize() {
|
||||
return _encodedTokenLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Formula} object from a supplied {@link Ptg} array.
|
||||
* Handles <code>null</code>s OK.
|
||||
* @param ptgs may be <code>null</code>
|
||||
* @return Never <code>null</code> (Possibly empty if the supplied <tt>ptgs</tt> is <code>null</code>)
|
||||
*/
|
||||
public static Formula create(Ptg[] ptgs) {
|
||||
if (ptgs == null || ptgs.length < 1) {
|
||||
return EMPTY;
|
||||
}
|
||||
int totalSize = Ptg.getEncodedSize(ptgs);
|
||||
byte[] encodedData = new byte[totalSize];
|
||||
Ptg.serializePtgs(ptgs, encodedData, 0);
|
||||
int encodedTokenLen = Ptg.getEncodedSizeWithoutArrayData(ptgs);
|
||||
return new Formula(encodedData, encodedTokenLen);
|
||||
}
|
||||
/**
|
||||
* Gets the {@link Ptg} array from the supplied {@link Formula}.
|
||||
* Handles <code>null</code>s OK.
|
||||
*
|
||||
* @param formula may be <code>null</code>
|
||||
* @return possibly <code>null</code> (if the supplied <tt>formula</tt> is <code>null</code>)
|
||||
*/
|
||||
public static Ptg[] getTokens(Formula formula) {
|
||||
if (formula == null) {
|
||||
return null;
|
||||
}
|
||||
return formula.getTokens();
|
||||
}
|
||||
|
||||
public Formula copy() {
|
||||
// OK to return this because immutable
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the locator for the corresponding {@link SharedFormulaRecord}, {@link ArrayRecord} or
|
||||
* {@link TableRecord} if this formula belongs to such a grouping. The {@link CellReference}
|
||||
* returned by this method will match the top left corner of the range of that grouping.
|
||||
* The return value is usually not the same as the location of the cell containing this formula.
|
||||
*
|
||||
* @return the firstRow & firstColumn of an array formula or shared formula that this formula
|
||||
* belongs to. <code>null</code> if this formula is not part of an array or shared formula.
|
||||
*/
|
||||
public CellReference getExpReference() {
|
||||
byte[] data = _byteEncoding;
|
||||
if (data.length != 5) {
|
||||
// tExp and tTbl are always 5 bytes long, and the only ptg in the formula
|
||||
return null;
|
||||
}
|
||||
switch (data[0]) {
|
||||
case ExpPtg.sid:
|
||||
break;
|
||||
case TblPtg.sid:
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
int firstRow = LittleEndian.getUShort(data, 1);
|
||||
int firstColumn = LittleEndian.getUShort(data, 3);
|
||||
return new CellReference(firstRow, firstColumn);
|
||||
}
|
||||
public boolean isSame(Formula other) {
|
||||
return Arrays.equals(_byteEncoding, other._byteEncoding);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.hssf.record.ArrayRecord;
|
||||
import org.apache.poi.hssf.record.SharedFormulaRecord;
|
||||
import org.apache.poi.hssf.record.TableRecord;
|
||||
import org.apache.poi.hssf.record.formula.ExpPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.TblPtg;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Encapsulates an encoded formula token array.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class Formula {
|
||||
|
||||
private static final Formula EMPTY = new Formula(new byte[0], 0);
|
||||
|
||||
/** immutable */
|
||||
private final byte[] _byteEncoding;
|
||||
private final int _encodedTokenLen;
|
||||
|
||||
private Formula(byte[] byteEncoding, int encodedTokenLen) {
|
||||
_byteEncoding = byteEncoding;
|
||||
_encodedTokenLen = encodedTokenLen;
|
||||
if (false) { // set to true to eagerly check Ptg decoding
|
||||
LittleEndianByteArrayInputStream in = new LittleEndianByteArrayInputStream(byteEncoding);
|
||||
Ptg.readTokens(encodedTokenLen, in);
|
||||
int nUnusedBytes = _byteEncoding.length - in.getReadIndex();
|
||||
if (nUnusedBytes > 0) {
|
||||
// TODO - this seems to occur when IntersectionPtg is present
|
||||
// This example file "IntersectionPtg.xls"
|
||||
// used by test: TestIntersectionPtg.testReading()
|
||||
// has 10 bytes unused at the end of the formula
|
||||
// 10 extra bytes are just 0x01 and 0x00
|
||||
System.out.println(nUnusedBytes + " unused bytes at end of formula");
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Convenience method for {@link #read(int, LittleEndianInput, int)}
|
||||
*/
|
||||
public static Formula read(int encodedTokenLen, LittleEndianInput in) {
|
||||
return read(encodedTokenLen, in, encodedTokenLen);
|
||||
}
|
||||
/**
|
||||
* When there are no array constants present, <tt>encodedTokenLen</tt>==<tt>totalEncodedLen</tt>
|
||||
* @param encodedTokenLen number of bytes in the stream taken by the plain formula tokens
|
||||
* @param totalEncodedLen the total number of bytes in the formula (includes trailing encoding
|
||||
* for array constants, but does not include 2 bytes for initial <tt>ushort encodedTokenLen</tt> field.
|
||||
* @return A new formula object as read from the stream. Possibly empty, never <code>null</code>.
|
||||
*/
|
||||
public static Formula read(int encodedTokenLen, LittleEndianInput in, int totalEncodedLen) {
|
||||
byte[] byteEncoding = new byte[totalEncodedLen];
|
||||
in.readFully(byteEncoding);
|
||||
return new Formula(byteEncoding, encodedTokenLen);
|
||||
}
|
||||
|
||||
public Ptg[] getTokens() {
|
||||
LittleEndianInput in = new LittleEndianByteArrayInputStream(_byteEncoding);
|
||||
return Ptg.readTokens(_encodedTokenLen, in);
|
||||
}
|
||||
/**
|
||||
* Writes The formula encoding is includes:
|
||||
* <ul>
|
||||
* <li>ushort tokenDataLen</li>
|
||||
* <li>tokenData</li>
|
||||
* <li>arrayConstantData (if present)</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(_encodedTokenLen);
|
||||
out.write(_byteEncoding);
|
||||
}
|
||||
|
||||
public void serializeTokens(LittleEndianOutput out) {
|
||||
out.write(_byteEncoding, 0, _encodedTokenLen);
|
||||
}
|
||||
public void serializeArrayConstantData(LittleEndianOutput out) {
|
||||
int len = _byteEncoding.length-_encodedTokenLen;
|
||||
out.write(_byteEncoding, _encodedTokenLen, len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return total formula encoding length. The formula encoding includes:
|
||||
* <ul>
|
||||
* <li>ushort tokenDataLen</li>
|
||||
* <li>tokenData</li>
|
||||
* <li>arrayConstantData (optional)</li>
|
||||
* </ul>
|
||||
* Note - this value is different to <tt>tokenDataLength</tt>
|
||||
*/
|
||||
public int getEncodedSize() {
|
||||
return 2 + _byteEncoding.length;
|
||||
}
|
||||
/**
|
||||
* This method is often used when the formula length does not appear immediately before
|
||||
* the encoded token data.
|
||||
*
|
||||
* @return the encoded length of the plain formula tokens. This does <em>not</em> include
|
||||
* the leading ushort field, nor any trailing array constant data.
|
||||
*/
|
||||
public int getEncodedTokenSize() {
|
||||
return _encodedTokenLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Formula} object from a supplied {@link Ptg} array.
|
||||
* Handles <code>null</code>s OK.
|
||||
* @param ptgs may be <code>null</code>
|
||||
* @return Never <code>null</code> (Possibly empty if the supplied <tt>ptgs</tt> is <code>null</code>)
|
||||
*/
|
||||
public static Formula create(Ptg[] ptgs) {
|
||||
if (ptgs == null || ptgs.length < 1) {
|
||||
return EMPTY;
|
||||
}
|
||||
int totalSize = Ptg.getEncodedSize(ptgs);
|
||||
byte[] encodedData = new byte[totalSize];
|
||||
Ptg.serializePtgs(ptgs, encodedData, 0);
|
||||
int encodedTokenLen = Ptg.getEncodedSizeWithoutArrayData(ptgs);
|
||||
return new Formula(encodedData, encodedTokenLen);
|
||||
}
|
||||
/**
|
||||
* Gets the {@link Ptg} array from the supplied {@link Formula}.
|
||||
* Handles <code>null</code>s OK.
|
||||
*
|
||||
* @param formula may be <code>null</code>
|
||||
* @return possibly <code>null</code> (if the supplied <tt>formula</tt> is <code>null</code>)
|
||||
*/
|
||||
public static Ptg[] getTokens(Formula formula) {
|
||||
if (formula == null) {
|
||||
return null;
|
||||
}
|
||||
return formula.getTokens();
|
||||
}
|
||||
|
||||
public Formula copy() {
|
||||
// OK to return this because immutable
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the locator for the corresponding {@link SharedFormulaRecord}, {@link ArrayRecord} or
|
||||
* {@link TableRecord} if this formula belongs to such a grouping. The {@link CellReference}
|
||||
* returned by this method will match the top left corner of the range of that grouping.
|
||||
* The return value is usually not the same as the location of the cell containing this formula.
|
||||
*
|
||||
* @return the firstRow & firstColumn of an array formula or shared formula that this formula
|
||||
* belongs to. <code>null</code> if this formula is not part of an array or shared formula.
|
||||
*/
|
||||
public CellReference getExpReference() {
|
||||
byte[] data = _byteEncoding;
|
||||
if (data.length != 5) {
|
||||
// tExp and tTbl are always 5 bytes long, and the only ptg in the formula
|
||||
return null;
|
||||
}
|
||||
switch (data[0]) {
|
||||
case ExpPtg.sid:
|
||||
break;
|
||||
case TblPtg.sid:
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
int firstRow = LittleEndian.getUShort(data, 1);
|
||||
int firstColumn = LittleEndian.getUShort(data, 3);
|
||||
return new CellReference(firstRow, firstColumn);
|
||||
}
|
||||
public boolean isSame(Formula other) {
|
||||
return Arrays.equals(_byteEncoding, other._byteEncoding);
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +1,55 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
|
||||
/**
|
||||
* Abstracts a workbook for the purpose of formula parsing.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface FormulaParsingWorkbook {
|
||||
/**
|
||||
* named range name matching is case insensitive
|
||||
*/
|
||||
EvaluationName getName(String name, int sheetIndex);
|
||||
|
||||
NameXPtg getNameXPtg(String name);
|
||||
|
||||
/**
|
||||
* gets the externSheet index for a sheet from this workbook
|
||||
*/
|
||||
int getExternalSheetIndex(String sheetName);
|
||||
/**
|
||||
* gets the externSheet index for a sheet from an external workbook
|
||||
* @param workbookName e.g. "Budget.xls"
|
||||
* @param sheetName a name of a sheet in that workbook
|
||||
*/
|
||||
int getExternalSheetIndex(String workbookName, String sheetName);
|
||||
|
||||
/**
|
||||
* Returns an enum holding spreadhseet properties specific to an Excel version (
|
||||
* max column and row numbers, max arguments to a function, etc.)
|
||||
*/
|
||||
SpreadsheetVersion getSpreadsheetVersion();
|
||||
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
|
||||
/**
|
||||
* Abstracts a workbook for the purpose of formula parsing.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface FormulaParsingWorkbook {
|
||||
/**
|
||||
* named range name matching is case insensitive
|
||||
*/
|
||||
EvaluationName getName(String name, int sheetIndex);
|
||||
|
||||
NameXPtg getNameXPtg(String name);
|
||||
|
||||
/**
|
||||
* gets the externSheet index for a sheet from this workbook
|
||||
*/
|
||||
int getExternalSheetIndex(String sheetName);
|
||||
/**
|
||||
* gets the externSheet index for a sheet from an external workbook
|
||||
* @param workbookName e.g. "Budget.xls"
|
||||
* @param sheetName a name of a sheet in that workbook
|
||||
*/
|
||||
int getExternalSheetIndex(String workbookName, String sheetName);
|
||||
|
||||
/**
|
||||
* Returns an enum holding spreadhseet properties specific to an Excel version (
|
||||
* max column and row numbers, max arguments to a function, etc.)
|
||||
*/
|
||||
SpreadsheetVersion getSpreadsheetVersion();
|
||||
|
||||
}
|
||||
|
@ -1,131 +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.ss.formula;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AttrPtg;
|
||||
import org.apache.poi.hssf.record.formula.MemAreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.MemErrPtg;
|
||||
import org.apache.poi.hssf.record.formula.MemFuncPtg;
|
||||
import org.apache.poi.hssf.record.formula.OperationPtg;
|
||||
import org.apache.poi.hssf.record.formula.ParenthesisPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
|
||||
/**
|
||||
* Common logic for rendering formulas.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class FormulaRenderer {
|
||||
|
||||
/**
|
||||
* Static method to convert an array of {@link Ptg}s in RPN order
|
||||
* to a human readable string format in infix mode.
|
||||
* @param book used for defined names and 3D references
|
||||
* @param ptgs must not be <code>null</code>
|
||||
* @return a human readable String
|
||||
*/
|
||||
public static String toFormulaString(FormulaRenderingWorkbook book, Ptg[] ptgs) {
|
||||
if (ptgs == null || ptgs.length == 0) {
|
||||
throw new IllegalArgumentException("ptgs must not be null");
|
||||
}
|
||||
Stack<String> stack = new Stack<String>();
|
||||
|
||||
for (int i=0 ; i < ptgs.length; i++) {
|
||||
Ptg ptg = ptgs[i];
|
||||
// TODO - what about MemNoMemPtg?
|
||||
if(ptg instanceof MemAreaPtg || ptg instanceof MemFuncPtg || ptg instanceof MemErrPtg) {
|
||||
// marks the start of a list of area expressions which will be naturally combined
|
||||
// by their trailing operators (e.g. UnionPtg)
|
||||
// TODO - put comment and throw exception in toFormulaString() of these classes
|
||||
continue;
|
||||
}
|
||||
if (ptg instanceof ParenthesisPtg) {
|
||||
String contents = stack.pop();
|
||||
stack.push ("(" + contents + ")");
|
||||
continue;
|
||||
}
|
||||
if (ptg instanceof AttrPtg) {
|
||||
AttrPtg attrPtg = ((AttrPtg) ptg);
|
||||
if (attrPtg.isOptimizedIf() || attrPtg.isOptimizedChoose() || attrPtg.isGoto()) {
|
||||
continue;
|
||||
}
|
||||
if (attrPtg.isSpace()) {
|
||||
// POI currently doesn't render spaces in formulas
|
||||
continue;
|
||||
// but if it ever did, care must be taken:
|
||||
// tAttrSpace comes *before* the operand it applies to, which may be consistent
|
||||
// with how the formula text appears but is against the RPN ordering assumed here
|
||||
}
|
||||
if (attrPtg.isSemiVolatile()) {
|
||||
// similar to tAttrSpace - RPN is violated
|
||||
continue;
|
||||
}
|
||||
if (attrPtg.isSum()) {
|
||||
String[] operands = getOperands(stack, attrPtg.getNumberOfOperands());
|
||||
stack.push(attrPtg.toFormulaString(operands));
|
||||
continue;
|
||||
}
|
||||
throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
|
||||
}
|
||||
|
||||
if (ptg instanceof WorkbookDependentFormula) {
|
||||
WorkbookDependentFormula optg = (WorkbookDependentFormula) ptg;
|
||||
stack.push(optg.toFormulaString(book));
|
||||
continue;
|
||||
}
|
||||
if (! (ptg instanceof OperationPtg)) {
|
||||
stack.push(ptg.toFormulaString());
|
||||
continue;
|
||||
}
|
||||
|
||||
OperationPtg o = (OperationPtg) ptg;
|
||||
String[] operands = getOperands(stack, o.getNumberOfOperands());
|
||||
stack.push(o.toFormulaString(operands));
|
||||
}
|
||||
if(stack.isEmpty()) {
|
||||
// inspection of the code above reveals that every stack.pop() is followed by a
|
||||
// stack.push(). So this is either an internal error or impossible.
|
||||
throw new IllegalStateException("Stack underflow");
|
||||
}
|
||||
String result = stack.pop();
|
||||
if(!stack.isEmpty()) {
|
||||
// Might be caused by some tokens like AttrPtg and Mem*Ptg, which really shouldn't
|
||||
// put anything on the stack
|
||||
throw new IllegalStateException("too much stuff left on the stack");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String[] getOperands(Stack<String> stack, int nOperands) {
|
||||
String[] operands = new String[nOperands];
|
||||
|
||||
for (int j = nOperands-1; j >= 0; j--) { // reverse iteration because args were pushed in-order
|
||||
if(stack.isEmpty()) {
|
||||
String msg = "Too few arguments supplied to operation. Expected (" + nOperands
|
||||
+ ") operands but got (" + (nOperands - j - 1) + ")";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
operands[j] = stack.pop();
|
||||
}
|
||||
return operands;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AttrPtg;
|
||||
import org.apache.poi.hssf.record.formula.MemAreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.MemErrPtg;
|
||||
import org.apache.poi.hssf.record.formula.MemFuncPtg;
|
||||
import org.apache.poi.hssf.record.formula.OperationPtg;
|
||||
import org.apache.poi.hssf.record.formula.ParenthesisPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
|
||||
/**
|
||||
* Common logic for rendering formulas.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class FormulaRenderer {
|
||||
|
||||
/**
|
||||
* Static method to convert an array of {@link Ptg}s in RPN order
|
||||
* to a human readable string format in infix mode.
|
||||
* @param book used for defined names and 3D references
|
||||
* @param ptgs must not be <code>null</code>
|
||||
* @return a human readable String
|
||||
*/
|
||||
public static String toFormulaString(FormulaRenderingWorkbook book, Ptg[] ptgs) {
|
||||
if (ptgs == null || ptgs.length == 0) {
|
||||
throw new IllegalArgumentException("ptgs must not be null");
|
||||
}
|
||||
Stack<String> stack = new Stack<String>();
|
||||
|
||||
for (int i=0 ; i < ptgs.length; i++) {
|
||||
Ptg ptg = ptgs[i];
|
||||
// TODO - what about MemNoMemPtg?
|
||||
if(ptg instanceof MemAreaPtg || ptg instanceof MemFuncPtg || ptg instanceof MemErrPtg) {
|
||||
// marks the start of a list of area expressions which will be naturally combined
|
||||
// by their trailing operators (e.g. UnionPtg)
|
||||
// TODO - put comment and throw exception in toFormulaString() of these classes
|
||||
continue;
|
||||
}
|
||||
if (ptg instanceof ParenthesisPtg) {
|
||||
String contents = stack.pop();
|
||||
stack.push ("(" + contents + ")");
|
||||
continue;
|
||||
}
|
||||
if (ptg instanceof AttrPtg) {
|
||||
AttrPtg attrPtg = ((AttrPtg) ptg);
|
||||
if (attrPtg.isOptimizedIf() || attrPtg.isOptimizedChoose() || attrPtg.isGoto()) {
|
||||
continue;
|
||||
}
|
||||
if (attrPtg.isSpace()) {
|
||||
// POI currently doesn't render spaces in formulas
|
||||
continue;
|
||||
// but if it ever did, care must be taken:
|
||||
// tAttrSpace comes *before* the operand it applies to, which may be consistent
|
||||
// with how the formula text appears but is against the RPN ordering assumed here
|
||||
}
|
||||
if (attrPtg.isSemiVolatile()) {
|
||||
// similar to tAttrSpace - RPN is violated
|
||||
continue;
|
||||
}
|
||||
if (attrPtg.isSum()) {
|
||||
String[] operands = getOperands(stack, attrPtg.getNumberOfOperands());
|
||||
stack.push(attrPtg.toFormulaString(operands));
|
||||
continue;
|
||||
}
|
||||
throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
|
||||
}
|
||||
|
||||
if (ptg instanceof WorkbookDependentFormula) {
|
||||
WorkbookDependentFormula optg = (WorkbookDependentFormula) ptg;
|
||||
stack.push(optg.toFormulaString(book));
|
||||
continue;
|
||||
}
|
||||
if (! (ptg instanceof OperationPtg)) {
|
||||
stack.push(ptg.toFormulaString());
|
||||
continue;
|
||||
}
|
||||
|
||||
OperationPtg o = (OperationPtg) ptg;
|
||||
String[] operands = getOperands(stack, o.getNumberOfOperands());
|
||||
stack.push(o.toFormulaString(operands));
|
||||
}
|
||||
if(stack.isEmpty()) {
|
||||
// inspection of the code above reveals that every stack.pop() is followed by a
|
||||
// stack.push(). So this is either an internal error or impossible.
|
||||
throw new IllegalStateException("Stack underflow");
|
||||
}
|
||||
String result = stack.pop();
|
||||
if(!stack.isEmpty()) {
|
||||
// Might be caused by some tokens like AttrPtg and Mem*Ptg, which really shouldn't
|
||||
// put anything on the stack
|
||||
throw new IllegalStateException("too much stuff left on the stack");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String[] getOperands(Stack<String> stack, int nOperands) {
|
||||
String[] operands = new String[nOperands];
|
||||
|
||||
for (int j = nOperands-1; j >= 0; j--) { // reverse iteration because args were pushed in-order
|
||||
if(stack.isEmpty()) {
|
||||
String msg = "Too few arguments supplied to operation. Expected (" + nOperands
|
||||
+ ") operands but got (" + (nOperands - j - 1) + ")";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
operands[j] = stack.pop();
|
||||
}
|
||||
return operands;
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +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.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
|
||||
|
||||
/**
|
||||
* Abstracts a workbook for the purpose of converting formula to text.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface FormulaRenderingWorkbook {
|
||||
|
||||
/**
|
||||
* @return <code>null</code> if externSheetIndex refers to a sheet inside the current workbook
|
||||
*/
|
||||
ExternalSheet getExternalSheet(int externSheetIndex);
|
||||
String getSheetNameByExternSheet(int externSheetIndex);
|
||||
String resolveNameXText(NameXPtg nameXPtg);
|
||||
String getNameText(NamePtg namePtg);
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
|
||||
|
||||
/**
|
||||
* Abstracts a workbook for the purpose of converting formula to text.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface FormulaRenderingWorkbook {
|
||||
|
||||
/**
|
||||
* @return <code>null</code> if externSheetIndex refers to a sheet inside the current workbook
|
||||
*/
|
||||
ExternalSheet getExternalSheet(int externSheetIndex);
|
||||
String getSheetNameByExternSheet(int externSheetIndex);
|
||||
String resolveNameXText(NameXPtg nameXPtg);
|
||||
String getNameText(NamePtg namePtg);
|
||||
}
|
||||
|
@ -1,40 +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.ss.formula;
|
||||
|
||||
/**
|
||||
* Enumeration of various formula types.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class FormulaType {
|
||||
private FormulaType() {
|
||||
// no instances of this class
|
||||
}
|
||||
public static final int CELL = 0;
|
||||
public static final int SHARED = 1;
|
||||
public static final int ARRAY =2;
|
||||
public static final int CONDFORMAT = 3;
|
||||
public static final int NAMEDRANGE = 4;
|
||||
// this constant is currently very specific. The exact differences from general data
|
||||
// validation formulas or conditional format formulas is not known yet
|
||||
public static final int DATAVALIDATION_LIST = 5;
|
||||
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
/**
|
||||
* Enumeration of various formula types.<br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class FormulaType {
|
||||
private FormulaType() {
|
||||
// no instances of this class
|
||||
}
|
||||
public static final int CELL = 0;
|
||||
public static final int SHARED = 1;
|
||||
public static final int ARRAY =2;
|
||||
public static final int CONDFORMAT = 3;
|
||||
public static final int NAMEDRANGE = 4;
|
||||
// this constant is currently very specific. The exact differences from general data
|
||||
// validation formulas or conditional format formulas is not known yet
|
||||
public static final int DATAVALIDATION_LIST = 5;
|
||||
|
||||
}
|
||||
|
@ -1,68 +1,68 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaI;
|
||||
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEvalBase;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class LazyRefEval extends RefEvalBase {
|
||||
|
||||
private final SheetRefEvaluator _evaluator;
|
||||
|
||||
public LazyRefEval(RefPtg ptg, SheetRefEvaluator sre) {
|
||||
super(ptg.getRow(), ptg.getColumn());
|
||||
_evaluator = sre;
|
||||
}
|
||||
public LazyRefEval(Ref3DPtg ptg, SheetRefEvaluator sre) {
|
||||
super(ptg.getRow(), ptg.getColumn());
|
||||
_evaluator = sre;
|
||||
}
|
||||
|
||||
public ValueEval getInnerValueEval() {
|
||||
return _evaluator.getEvalForCell(getRow(), getColumn());
|
||||
}
|
||||
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
|
||||
|
||||
AreaI area = new OffsetArea(getRow(), getColumn(),
|
||||
relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
|
||||
|
||||
return new LazyAreaEval(area, _evaluator);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
CellReference cr = new CellReference(getRow(), getColumn());
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName()).append("[");
|
||||
sb.append(_evaluator.getSheetName());
|
||||
sb.append('!');
|
||||
sb.append(cr.formatAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaI;
|
||||
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEvalBase;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class LazyRefEval extends RefEvalBase {
|
||||
|
||||
private final SheetRefEvaluator _evaluator;
|
||||
|
||||
public LazyRefEval(RefPtg ptg, SheetRefEvaluator sre) {
|
||||
super(ptg.getRow(), ptg.getColumn());
|
||||
_evaluator = sre;
|
||||
}
|
||||
public LazyRefEval(Ref3DPtg ptg, SheetRefEvaluator sre) {
|
||||
super(ptg.getRow(), ptg.getColumn());
|
||||
_evaluator = sre;
|
||||
}
|
||||
|
||||
public ValueEval getInnerValueEval() {
|
||||
return _evaluator.getEvalForCell(getRow(), getColumn());
|
||||
}
|
||||
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
|
||||
|
||||
AreaI area = new OffsetArea(getRow(), getColumn(),
|
||||
relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
|
||||
|
||||
return new LazyAreaEval(area, _evaluator);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
CellReference cr = new CellReference(getRow(), getColumn());
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName()).append("[");
|
||||
sb.append(_evaluator.getSheetName());
|
||||
sb.append('!');
|
||||
sb.append(cr.formatAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +1,48 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class SheetRefEvaluator {
|
||||
|
||||
private final WorkbookEvaluator _bookEvaluator;
|
||||
private final EvaluationTracker _tracker;
|
||||
private final EvaluationSheet _sheet;
|
||||
private final int _sheetIndex;
|
||||
|
||||
public SheetRefEvaluator(WorkbookEvaluator bookEvaluator, EvaluationTracker tracker,
|
||||
EvaluationWorkbook _workbook, int sheetIndex) {
|
||||
_bookEvaluator = bookEvaluator;
|
||||
_tracker = tracker;
|
||||
_sheet = _workbook.getSheet(sheetIndex);
|
||||
_sheetIndex = sheetIndex;
|
||||
}
|
||||
|
||||
public String getSheetName() {
|
||||
return _bookEvaluator.getSheetName(_sheetIndex);
|
||||
}
|
||||
|
||||
public ValueEval getEvalForCell(int rowIndex, int columnIndex) {
|
||||
return _bookEvaluator.evaluateReference(_sheet, _sheetIndex, rowIndex, columnIndex, _tracker);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class SheetRefEvaluator {
|
||||
|
||||
private final WorkbookEvaluator _bookEvaluator;
|
||||
private final EvaluationTracker _tracker;
|
||||
private final EvaluationSheet _sheet;
|
||||
private final int _sheetIndex;
|
||||
|
||||
public SheetRefEvaluator(WorkbookEvaluator bookEvaluator, EvaluationTracker tracker,
|
||||
EvaluationWorkbook _workbook, int sheetIndex) {
|
||||
_bookEvaluator = bookEvaluator;
|
||||
_tracker = tracker;
|
||||
_sheet = _workbook.getSheet(sheetIndex);
|
||||
_sheetIndex = sheetIndex;
|
||||
}
|
||||
|
||||
public String getSheetName() {
|
||||
return _bookEvaluator.getSheetName(_sheetIndex);
|
||||
}
|
||||
|
||||
public ValueEval getEvalForCell(int rowIndex, int columnIndex) {
|
||||
return _bookEvaluator.evaluateReference(_sheet, _sheetIndex, rowIndex, columnIndex, _tracker);
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,30 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
/**
|
||||
* Should be implemented by any {@link org.apache.poi.hssf.record.formula.Ptg} subclass that needs a workbook to render its formula.
|
||||
* <br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface WorkbookDependentFormula {
|
||||
String toFormulaString(FormulaRenderingWorkbook book);
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
/**
|
||||
* Should be implemented by any {@link org.apache.poi.hssf.record.formula.Ptg} subclass that needs a workbook to render its formula.
|
||||
* <br/>
|
||||
*
|
||||
* For POI internal use only
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface WorkbookDependentFormula {
|
||||
String toFormulaString(FormulaRenderingWorkbook book);
|
||||
}
|
||||
|
@ -1,36 +1,36 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval;
|
||||
|
||||
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||
|
||||
/**
|
||||
* An exception thrown by implementors of {@link FormulaEvaluator} when attempting to evaluate
|
||||
* a formula which requires features that POI does not (yet) support.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class NotImplementedException extends RuntimeException {
|
||||
|
||||
public NotImplementedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
public NotImplementedException(String message, NotImplementedException cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval;
|
||||
|
||||
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||
|
||||
/**
|
||||
* An exception thrown by implementors of {@link FormulaEvaluator} when attempting to evaluate
|
||||
* a formula which requires features that POI does not (yet) support.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class NotImplementedException extends RuntimeException {
|
||||
|
||||
public NotImplementedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
public NotImplementedException(String message, NotImplementedException cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
@ -1,132 +1,132 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval.forked;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.BlankEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
|
||||
/**
|
||||
* Represents a cell being used for forked evaluation that has had a value set different from the
|
||||
* corresponding cell in the shared master workbook.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class ForkedEvaluationCell implements EvaluationCell {
|
||||
|
||||
private final EvaluationSheet _sheet;
|
||||
/** corresponding cell from master workbook */
|
||||
private final EvaluationCell _masterCell;
|
||||
private boolean _booleanValue;
|
||||
private int _cellType;
|
||||
private int _errorValue;
|
||||
private double _numberValue;
|
||||
private String _stringValue;
|
||||
|
||||
public ForkedEvaluationCell(ForkedEvaluationSheet sheet, EvaluationCell masterCell) {
|
||||
_sheet = sheet;
|
||||
_masterCell = masterCell;
|
||||
// start with value blank, but expect construction to be immediately
|
||||
setValue(BlankEval.INSTANCE); // followed by a proper call to setValue()
|
||||
}
|
||||
|
||||
public Object getIdentityKey() {
|
||||
return _masterCell.getIdentityKey();
|
||||
}
|
||||
|
||||
public void setValue(ValueEval value) {
|
||||
Class<? extends ValueEval> cls = value.getClass();
|
||||
|
||||
if (cls == NumberEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_NUMERIC;
|
||||
_numberValue = ((NumberEval)value).getNumberValue();
|
||||
return;
|
||||
}
|
||||
if (cls == StringEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_STRING;
|
||||
_stringValue = ((StringEval)value).getStringValue();
|
||||
return;
|
||||
}
|
||||
if (cls == BoolEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_BOOLEAN;
|
||||
_booleanValue = ((BoolEval)value).getBooleanValue();
|
||||
return;
|
||||
}
|
||||
if (cls == ErrorEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_ERROR;
|
||||
_errorValue = ((ErrorEval)value).getErrorCode();
|
||||
return;
|
||||
}
|
||||
if (cls == BlankEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_BLANK;
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException("Unexpected value class (" + cls.getName() + ")");
|
||||
}
|
||||
public void copyValue(Cell destCell) {
|
||||
switch (_cellType) {
|
||||
case Cell.CELL_TYPE_BLANK: destCell.setCellType(Cell.CELL_TYPE_BLANK); return;
|
||||
case Cell.CELL_TYPE_NUMERIC: destCell.setCellValue(_numberValue); return;
|
||||
case Cell.CELL_TYPE_BOOLEAN: destCell.setCellValue(_booleanValue); return;
|
||||
case Cell.CELL_TYPE_STRING: destCell.setCellValue(_stringValue); return;
|
||||
case Cell.CELL_TYPE_ERROR: destCell.setCellErrorValue((byte)_errorValue); return;
|
||||
}
|
||||
throw new IllegalStateException("Unexpected data type (" + _cellType + ")");
|
||||
}
|
||||
|
||||
private void checkCellType(int expectedCellType) {
|
||||
if (_cellType != expectedCellType) {
|
||||
throw new RuntimeException("Wrong data type (" + _cellType + ")");
|
||||
}
|
||||
}
|
||||
public int getCellType() {
|
||||
return _cellType;
|
||||
}
|
||||
public boolean getBooleanCellValue() {
|
||||
checkCellType(HSSFCell.CELL_TYPE_BOOLEAN);
|
||||
return _booleanValue;
|
||||
}
|
||||
public int getErrorCellValue() {
|
||||
checkCellType(HSSFCell.CELL_TYPE_ERROR);
|
||||
return _errorValue;
|
||||
}
|
||||
public double getNumericCellValue() {
|
||||
checkCellType(HSSFCell.CELL_TYPE_NUMERIC);
|
||||
return _numberValue;
|
||||
}
|
||||
public String getStringCellValue() {
|
||||
checkCellType(HSSFCell.CELL_TYPE_STRING);
|
||||
return _stringValue;
|
||||
}
|
||||
public EvaluationSheet getSheet() {
|
||||
return _sheet;
|
||||
}
|
||||
public int getRowIndex() {
|
||||
return _masterCell.getRowIndex();
|
||||
}
|
||||
public int getColumnIndex() {
|
||||
return _masterCell.getColumnIndex();
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval.forked;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.BlankEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
|
||||
/**
|
||||
* Represents a cell being used for forked evaluation that has had a value set different from the
|
||||
* corresponding cell in the shared master workbook.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class ForkedEvaluationCell implements EvaluationCell {
|
||||
|
||||
private final EvaluationSheet _sheet;
|
||||
/** corresponding cell from master workbook */
|
||||
private final EvaluationCell _masterCell;
|
||||
private boolean _booleanValue;
|
||||
private int _cellType;
|
||||
private int _errorValue;
|
||||
private double _numberValue;
|
||||
private String _stringValue;
|
||||
|
||||
public ForkedEvaluationCell(ForkedEvaluationSheet sheet, EvaluationCell masterCell) {
|
||||
_sheet = sheet;
|
||||
_masterCell = masterCell;
|
||||
// start with value blank, but expect construction to be immediately
|
||||
setValue(BlankEval.INSTANCE); // followed by a proper call to setValue()
|
||||
}
|
||||
|
||||
public Object getIdentityKey() {
|
||||
return _masterCell.getIdentityKey();
|
||||
}
|
||||
|
||||
public void setValue(ValueEval value) {
|
||||
Class<? extends ValueEval> cls = value.getClass();
|
||||
|
||||
if (cls == NumberEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_NUMERIC;
|
||||
_numberValue = ((NumberEval)value).getNumberValue();
|
||||
return;
|
||||
}
|
||||
if (cls == StringEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_STRING;
|
||||
_stringValue = ((StringEval)value).getStringValue();
|
||||
return;
|
||||
}
|
||||
if (cls == BoolEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_BOOLEAN;
|
||||
_booleanValue = ((BoolEval)value).getBooleanValue();
|
||||
return;
|
||||
}
|
||||
if (cls == ErrorEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_ERROR;
|
||||
_errorValue = ((ErrorEval)value).getErrorCode();
|
||||
return;
|
||||
}
|
||||
if (cls == BlankEval.class) {
|
||||
_cellType = HSSFCell.CELL_TYPE_BLANK;
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException("Unexpected value class (" + cls.getName() + ")");
|
||||
}
|
||||
public void copyValue(Cell destCell) {
|
||||
switch (_cellType) {
|
||||
case Cell.CELL_TYPE_BLANK: destCell.setCellType(Cell.CELL_TYPE_BLANK); return;
|
||||
case Cell.CELL_TYPE_NUMERIC: destCell.setCellValue(_numberValue); return;
|
||||
case Cell.CELL_TYPE_BOOLEAN: destCell.setCellValue(_booleanValue); return;
|
||||
case Cell.CELL_TYPE_STRING: destCell.setCellValue(_stringValue); return;
|
||||
case Cell.CELL_TYPE_ERROR: destCell.setCellErrorValue((byte)_errorValue); return;
|
||||
}
|
||||
throw new IllegalStateException("Unexpected data type (" + _cellType + ")");
|
||||
}
|
||||
|
||||
private void checkCellType(int expectedCellType) {
|
||||
if (_cellType != expectedCellType) {
|
||||
throw new RuntimeException("Wrong data type (" + _cellType + ")");
|
||||
}
|
||||
}
|
||||
public int getCellType() {
|
||||
return _cellType;
|
||||
}
|
||||
public boolean getBooleanCellValue() {
|
||||
checkCellType(HSSFCell.CELL_TYPE_BOOLEAN);
|
||||
return _booleanValue;
|
||||
}
|
||||
public int getErrorCellValue() {
|
||||
checkCellType(HSSFCell.CELL_TYPE_ERROR);
|
||||
return _errorValue;
|
||||
}
|
||||
public double getNumericCellValue() {
|
||||
checkCellType(HSSFCell.CELL_TYPE_NUMERIC);
|
||||
return _numberValue;
|
||||
}
|
||||
public String getStringCellValue() {
|
||||
checkCellType(HSSFCell.CELL_TYPE_STRING);
|
||||
return _stringValue;
|
||||
}
|
||||
public EvaluationSheet getSheet() {
|
||||
return _sheet;
|
||||
}
|
||||
public int getRowIndex() {
|
||||
return _masterCell.getRowIndex();
|
||||
}
|
||||
public int getColumnIndex() {
|
||||
return _masterCell.getColumnIndex();
|
||||
}
|
||||
}
|
||||
|
@ -1,129 +1,129 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval.forked;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
|
||||
/**
|
||||
* Represents a sheet being used for forked evaluation. Initially, objects of this class contain
|
||||
* only the cells from the master workbook. By calling {@link #getOrCreateUpdatableCell(int, int)},
|
||||
* the master cell object is logically replaced with a {@link ForkedEvaluationCell} instance, which
|
||||
* will be used in all subsequent evaluations.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class ForkedEvaluationSheet implements EvaluationSheet {
|
||||
|
||||
private final EvaluationSheet _masterSheet;
|
||||
/**
|
||||
* Only cells which have been split are put in this map. (This has been done to conserve memory).
|
||||
*/
|
||||
private final Map<RowColKey, ForkedEvaluationCell> _sharedCellsByRowCol;
|
||||
|
||||
public ForkedEvaluationSheet(EvaluationSheet masterSheet) {
|
||||
_masterSheet = masterSheet;
|
||||
_sharedCellsByRowCol = new HashMap<RowColKey, ForkedEvaluationCell>();
|
||||
}
|
||||
|
||||
public EvaluationCell getCell(int rowIndex, int columnIndex) {
|
||||
RowColKey key = new RowColKey(rowIndex, columnIndex);
|
||||
|
||||
ForkedEvaluationCell result = _sharedCellsByRowCol.get(key);
|
||||
if (result == null) {
|
||||
return _masterSheet.getCell(rowIndex, columnIndex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public ForkedEvaluationCell getOrCreateUpdatableCell(int rowIndex, int columnIndex) {
|
||||
RowColKey key = new RowColKey(rowIndex, columnIndex);
|
||||
|
||||
ForkedEvaluationCell result = _sharedCellsByRowCol.get(key);
|
||||
if (result == null) {
|
||||
EvaluationCell mcell = _masterSheet.getCell(rowIndex, columnIndex);
|
||||
result = new ForkedEvaluationCell(this, mcell);
|
||||
_sharedCellsByRowCol.put(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void copyUpdatedCells(Sheet sheet) {
|
||||
RowColKey[] keys = new RowColKey[_sharedCellsByRowCol.size()];
|
||||
_sharedCellsByRowCol.keySet().toArray(keys);
|
||||
Arrays.sort(keys);
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
RowColKey key = keys[i];
|
||||
Row row = sheet.getRow(key.getRowIndex());
|
||||
if (row == null) {
|
||||
row = sheet.createRow(key.getRowIndex());
|
||||
}
|
||||
Cell destCell = row.getCell(key.getColumnIndex());
|
||||
if (destCell == null) {
|
||||
destCell = row.createCell(key.getColumnIndex());
|
||||
}
|
||||
|
||||
ForkedEvaluationCell srcCell = _sharedCellsByRowCol.get(key);
|
||||
srcCell.copyValue(destCell);
|
||||
}
|
||||
}
|
||||
|
||||
public int getSheetIndex(EvaluationWorkbook mewb) {
|
||||
return mewb.getSheetIndex(_masterSheet);
|
||||
}
|
||||
|
||||
private static final class RowColKey implements Comparable<RowColKey>{
|
||||
private final int _rowIndex;
|
||||
private final int _columnIndex;
|
||||
|
||||
public RowColKey(int rowIndex, int columnIndex) {
|
||||
_rowIndex = rowIndex;
|
||||
_columnIndex = columnIndex;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
RowColKey other = (RowColKey) obj;
|
||||
return _rowIndex == other._rowIndex && _columnIndex == other._columnIndex;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return _rowIndex ^ _columnIndex;
|
||||
}
|
||||
public int compareTo(RowColKey o) {
|
||||
int cmp = _rowIndex - o._rowIndex;
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
return _columnIndex - o._columnIndex;
|
||||
}
|
||||
public int getRowIndex() {
|
||||
return _rowIndex;
|
||||
}
|
||||
public int getColumnIndex() {
|
||||
return _columnIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval.forked;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
|
||||
/**
|
||||
* Represents a sheet being used for forked evaluation. Initially, objects of this class contain
|
||||
* only the cells from the master workbook. By calling {@link #getOrCreateUpdatableCell(int, int)},
|
||||
* the master cell object is logically replaced with a {@link ForkedEvaluationCell} instance, which
|
||||
* will be used in all subsequent evaluations.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class ForkedEvaluationSheet implements EvaluationSheet {
|
||||
|
||||
private final EvaluationSheet _masterSheet;
|
||||
/**
|
||||
* Only cells which have been split are put in this map. (This has been done to conserve memory).
|
||||
*/
|
||||
private final Map<RowColKey, ForkedEvaluationCell> _sharedCellsByRowCol;
|
||||
|
||||
public ForkedEvaluationSheet(EvaluationSheet masterSheet) {
|
||||
_masterSheet = masterSheet;
|
||||
_sharedCellsByRowCol = new HashMap<RowColKey, ForkedEvaluationCell>();
|
||||
}
|
||||
|
||||
public EvaluationCell getCell(int rowIndex, int columnIndex) {
|
||||
RowColKey key = new RowColKey(rowIndex, columnIndex);
|
||||
|
||||
ForkedEvaluationCell result = _sharedCellsByRowCol.get(key);
|
||||
if (result == null) {
|
||||
return _masterSheet.getCell(rowIndex, columnIndex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public ForkedEvaluationCell getOrCreateUpdatableCell(int rowIndex, int columnIndex) {
|
||||
RowColKey key = new RowColKey(rowIndex, columnIndex);
|
||||
|
||||
ForkedEvaluationCell result = _sharedCellsByRowCol.get(key);
|
||||
if (result == null) {
|
||||
EvaluationCell mcell = _masterSheet.getCell(rowIndex, columnIndex);
|
||||
result = new ForkedEvaluationCell(this, mcell);
|
||||
_sharedCellsByRowCol.put(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void copyUpdatedCells(Sheet sheet) {
|
||||
RowColKey[] keys = new RowColKey[_sharedCellsByRowCol.size()];
|
||||
_sharedCellsByRowCol.keySet().toArray(keys);
|
||||
Arrays.sort(keys);
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
RowColKey key = keys[i];
|
||||
Row row = sheet.getRow(key.getRowIndex());
|
||||
if (row == null) {
|
||||
row = sheet.createRow(key.getRowIndex());
|
||||
}
|
||||
Cell destCell = row.getCell(key.getColumnIndex());
|
||||
if (destCell == null) {
|
||||
destCell = row.createCell(key.getColumnIndex());
|
||||
}
|
||||
|
||||
ForkedEvaluationCell srcCell = _sharedCellsByRowCol.get(key);
|
||||
srcCell.copyValue(destCell);
|
||||
}
|
||||
}
|
||||
|
||||
public int getSheetIndex(EvaluationWorkbook mewb) {
|
||||
return mewb.getSheetIndex(_masterSheet);
|
||||
}
|
||||
|
||||
private static final class RowColKey implements Comparable<RowColKey>{
|
||||
private final int _rowIndex;
|
||||
private final int _columnIndex;
|
||||
|
||||
public RowColKey(int rowIndex, int columnIndex) {
|
||||
_rowIndex = rowIndex;
|
||||
_columnIndex = columnIndex;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
RowColKey other = (RowColKey) obj;
|
||||
return _rowIndex == other._rowIndex && _columnIndex == other._columnIndex;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return _rowIndex ^ _columnIndex;
|
||||
}
|
||||
public int compareTo(RowColKey o) {
|
||||
int cmp = _rowIndex - o._rowIndex;
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
return _columnIndex - o._columnIndex;
|
||||
}
|
||||
public int getRowIndex() {
|
||||
return _rowIndex;
|
||||
}
|
||||
public int getColumnIndex() {
|
||||
return _columnIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,144 +1,144 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval.forked;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationName;
|
||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
|
||||
/**
|
||||
* Represents a workbook being used for forked evaluation. Most operations are delegated to the
|
||||
* shared master workbook, except those that potentially involve cell values that may have been
|
||||
* updated after a call to {@link #getOrCreateUpdatableCell(String, int, int)}.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
||||
|
||||
private final EvaluationWorkbook _masterBook;
|
||||
private final Map<String, ForkedEvaluationSheet> _sharedSheetsByName;
|
||||
|
||||
public ForkedEvaluationWorkbook(EvaluationWorkbook master) {
|
||||
_masterBook = master;
|
||||
_sharedSheetsByName = new HashMap<String, ForkedEvaluationSheet>();
|
||||
}
|
||||
|
||||
public ForkedEvaluationCell getOrCreateUpdatableCell(String sheetName, int rowIndex,
|
||||
int columnIndex) {
|
||||
ForkedEvaluationSheet sheet = getSharedSheet(sheetName);
|
||||
return sheet.getOrCreateUpdatableCell(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
public EvaluationCell getEvaluationCell(String sheetName, int rowIndex, int columnIndex) {
|
||||
ForkedEvaluationSheet sheet = getSharedSheet(sheetName);
|
||||
return sheet.getCell(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
private ForkedEvaluationSheet getSharedSheet(String sheetName) {
|
||||
ForkedEvaluationSheet result = _sharedSheetsByName.get(sheetName);
|
||||
if (result == null) {
|
||||
result = new ForkedEvaluationSheet(_masterBook.getSheet(_masterBook
|
||||
.getSheetIndex(sheetName)));
|
||||
_sharedSheetsByName.put(sheetName, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void copyUpdatedCells(Workbook workbook) {
|
||||
String[] sheetNames = new String[_sharedSheetsByName.size()];
|
||||
_sharedSheetsByName.keySet().toArray(sheetNames);
|
||||
OrderedSheet[] oss = new OrderedSheet[sheetNames.length];
|
||||
for (int i = 0; i < sheetNames.length; i++) {
|
||||
String sheetName = sheetNames[i];
|
||||
oss[i] = new OrderedSheet(sheetName, _masterBook.getSheetIndex(sheetName));
|
||||
}
|
||||
for (int i = 0; i < oss.length; i++) {
|
||||
String sheetName = oss[i].getSheetName();
|
||||
ForkedEvaluationSheet sheet = _sharedSheetsByName.get(sheetName);
|
||||
sheet.copyUpdatedCells(workbook.getSheet(sheetName));
|
||||
}
|
||||
}
|
||||
|
||||
public int convertFromExternSheetIndex(int externSheetIndex) {
|
||||
return _masterBook.convertFromExternSheetIndex(externSheetIndex);
|
||||
}
|
||||
|
||||
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||
return _masterBook.getExternalSheet(externSheetIndex);
|
||||
}
|
||||
|
||||
public Ptg[] getFormulaTokens(EvaluationCell cell) {
|
||||
if (cell instanceof ForkedEvaluationCell) {
|
||||
// doesn't happen yet because formulas cannot be modified from the master workbook
|
||||
throw new RuntimeException("Updated formulas not supported yet");
|
||||
}
|
||||
return _masterBook.getFormulaTokens(cell);
|
||||
}
|
||||
|
||||
public EvaluationName getName(NamePtg namePtg) {
|
||||
return _masterBook.getName(namePtg);
|
||||
}
|
||||
|
||||
public EvaluationSheet getSheet(int sheetIndex) {
|
||||
return getSharedSheet(getSheetName(sheetIndex));
|
||||
}
|
||||
|
||||
public int getSheetIndex(EvaluationSheet sheet) {
|
||||
if (sheet instanceof ForkedEvaluationSheet) {
|
||||
ForkedEvaluationSheet mes = (ForkedEvaluationSheet) sheet;
|
||||
return mes.getSheetIndex(_masterBook);
|
||||
}
|
||||
return _masterBook.getSheetIndex(sheet);
|
||||
}
|
||||
|
||||
public int getSheetIndex(String sheetName) {
|
||||
return _masterBook.getSheetIndex(sheetName);
|
||||
}
|
||||
|
||||
public String getSheetName(int sheetIndex) {
|
||||
return _masterBook.getSheetName(sheetIndex);
|
||||
}
|
||||
|
||||
public String resolveNameXText(NameXPtg ptg) {
|
||||
return _masterBook.resolveNameXText(ptg);
|
||||
}
|
||||
|
||||
private static final class OrderedSheet implements Comparable<OrderedSheet> {
|
||||
private final String _sheetName;
|
||||
private final int _index;
|
||||
|
||||
public OrderedSheet(String sheetName, int index) {
|
||||
_sheetName = sheetName;
|
||||
_index = index;
|
||||
}
|
||||
public String getSheetName() {
|
||||
return _sheetName;
|
||||
}
|
||||
public int compareTo(OrderedSheet o) {
|
||||
return _index - o._index;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval.forked;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationName;
|
||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
|
||||
/**
|
||||
* Represents a workbook being used for forked evaluation. Most operations are delegated to the
|
||||
* shared master workbook, except those that potentially involve cell values that may have been
|
||||
* updated after a call to {@link #getOrCreateUpdatableCell(String, int, int)}.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
||||
|
||||
private final EvaluationWorkbook _masterBook;
|
||||
private final Map<String, ForkedEvaluationSheet> _sharedSheetsByName;
|
||||
|
||||
public ForkedEvaluationWorkbook(EvaluationWorkbook master) {
|
||||
_masterBook = master;
|
||||
_sharedSheetsByName = new HashMap<String, ForkedEvaluationSheet>();
|
||||
}
|
||||
|
||||
public ForkedEvaluationCell getOrCreateUpdatableCell(String sheetName, int rowIndex,
|
||||
int columnIndex) {
|
||||
ForkedEvaluationSheet sheet = getSharedSheet(sheetName);
|
||||
return sheet.getOrCreateUpdatableCell(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
public EvaluationCell getEvaluationCell(String sheetName, int rowIndex, int columnIndex) {
|
||||
ForkedEvaluationSheet sheet = getSharedSheet(sheetName);
|
||||
return sheet.getCell(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
private ForkedEvaluationSheet getSharedSheet(String sheetName) {
|
||||
ForkedEvaluationSheet result = _sharedSheetsByName.get(sheetName);
|
||||
if (result == null) {
|
||||
result = new ForkedEvaluationSheet(_masterBook.getSheet(_masterBook
|
||||
.getSheetIndex(sheetName)));
|
||||
_sharedSheetsByName.put(sheetName, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void copyUpdatedCells(Workbook workbook) {
|
||||
String[] sheetNames = new String[_sharedSheetsByName.size()];
|
||||
_sharedSheetsByName.keySet().toArray(sheetNames);
|
||||
OrderedSheet[] oss = new OrderedSheet[sheetNames.length];
|
||||
for (int i = 0; i < sheetNames.length; i++) {
|
||||
String sheetName = sheetNames[i];
|
||||
oss[i] = new OrderedSheet(sheetName, _masterBook.getSheetIndex(sheetName));
|
||||
}
|
||||
for (int i = 0; i < oss.length; i++) {
|
||||
String sheetName = oss[i].getSheetName();
|
||||
ForkedEvaluationSheet sheet = _sharedSheetsByName.get(sheetName);
|
||||
sheet.copyUpdatedCells(workbook.getSheet(sheetName));
|
||||
}
|
||||
}
|
||||
|
||||
public int convertFromExternSheetIndex(int externSheetIndex) {
|
||||
return _masterBook.convertFromExternSheetIndex(externSheetIndex);
|
||||
}
|
||||
|
||||
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||
return _masterBook.getExternalSheet(externSheetIndex);
|
||||
}
|
||||
|
||||
public Ptg[] getFormulaTokens(EvaluationCell cell) {
|
||||
if (cell instanceof ForkedEvaluationCell) {
|
||||
// doesn't happen yet because formulas cannot be modified from the master workbook
|
||||
throw new RuntimeException("Updated formulas not supported yet");
|
||||
}
|
||||
return _masterBook.getFormulaTokens(cell);
|
||||
}
|
||||
|
||||
public EvaluationName getName(NamePtg namePtg) {
|
||||
return _masterBook.getName(namePtg);
|
||||
}
|
||||
|
||||
public EvaluationSheet getSheet(int sheetIndex) {
|
||||
return getSharedSheet(getSheetName(sheetIndex));
|
||||
}
|
||||
|
||||
public int getSheetIndex(EvaluationSheet sheet) {
|
||||
if (sheet instanceof ForkedEvaluationSheet) {
|
||||
ForkedEvaluationSheet mes = (ForkedEvaluationSheet) sheet;
|
||||
return mes.getSheetIndex(_masterBook);
|
||||
}
|
||||
return _masterBook.getSheetIndex(sheet);
|
||||
}
|
||||
|
||||
public int getSheetIndex(String sheetName) {
|
||||
return _masterBook.getSheetIndex(sheetName);
|
||||
}
|
||||
|
||||
public String getSheetName(int sheetIndex) {
|
||||
return _masterBook.getSheetName(sheetIndex);
|
||||
}
|
||||
|
||||
public String resolveNameXText(NameXPtg ptg) {
|
||||
return _masterBook.resolveNameXText(ptg);
|
||||
}
|
||||
|
||||
private static final class OrderedSheet implements Comparable<OrderedSheet> {
|
||||
private final String _sheetName;
|
||||
private final int _index;
|
||||
|
||||
public OrderedSheet(String sheetName, int index) {
|
||||
_sheetName = sheetName;
|
||||
_index = index;
|
||||
}
|
||||
public String getSheetName() {
|
||||
return _sheetName;
|
||||
}
|
||||
public int compareTo(OrderedSheet o) {
|
||||
return _index - o._index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,133 +1,133 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval.forked;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||
import org.apache.poi.ss.formula.IStabilityClassifier;
|
||||
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
|
||||
/**
|
||||
* An alternative workbook evaluator that saves memory in situations where a single workbook is
|
||||
* concurrently and independently evaluated many times. With standard formula evaluation, around
|
||||
* 90% of memory consumption is due to loading of the {@link HSSFWorkbook} or {@link org.apache.poi.xssf.usermodel.XSSFWorkbook}.
|
||||
* This class enables a 'master workbook' to be loaded just once and shared between many evaluation
|
||||
* clients. Each evaluation client creates its own {@link ForkedEvaluator} and can set cell values
|
||||
* that will be used for local evaluations (and don't disturb evaluations on other evaluators).
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ForkedEvaluator {
|
||||
|
||||
private WorkbookEvaluator _evaluator;
|
||||
private ForkedEvaluationWorkbook _sewb;
|
||||
|
||||
private ForkedEvaluator(EvaluationWorkbook masterWorkbook, IStabilityClassifier stabilityClassifier) {
|
||||
_sewb = new ForkedEvaluationWorkbook(masterWorkbook);
|
||||
_evaluator = new WorkbookEvaluator(_sewb, stabilityClassifier);
|
||||
}
|
||||
private static EvaluationWorkbook createEvaluationWorkbook(Workbook wb) {
|
||||
if (wb instanceof HSSFWorkbook) {
|
||||
return HSSFEvaluationWorkbook.create((HSSFWorkbook) wb);
|
||||
}
|
||||
// TODO rearrange POI build to allow this
|
||||
// if (wb instanceof XSSFWorkbook) {
|
||||
// return XSSFEvaluationWorkbook.create((XSSFWorkbook) wb);
|
||||
// }
|
||||
throw new IllegalArgumentException("Unexpected workbook type (" + wb.getClass().getName() + ")");
|
||||
}
|
||||
public static ForkedEvaluator create(Workbook wb, IStabilityClassifier stabilityClassifier) {
|
||||
return new ForkedEvaluator(createEvaluationWorkbook(wb), stabilityClassifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified cell to the supplied <tt>value</tt>
|
||||
* @param sheetName the name of the sheet containing the cell
|
||||
* @param rowIndex zero based
|
||||
* @param columnIndex zero based
|
||||
*/
|
||||
public void updateCell(String sheetName, int rowIndex, int columnIndex, ValueEval value) {
|
||||
|
||||
ForkedEvaluationCell cell = _sewb.getOrCreateUpdatableCell(sheetName, rowIndex, columnIndex);
|
||||
cell.setValue(value);
|
||||
_evaluator.notifyUpdateCell(cell);
|
||||
}
|
||||
/**
|
||||
* Copies the values of all updated cells (modified by calls to {@link
|
||||
* #updateCell(String, int, int, ValueEval)}) to the supplied <tt>workbook</tt>.<br/>
|
||||
* Typically, the supplied <tt>workbook</tt> is a writable copy of the 'master workbook',
|
||||
* but at the very least it must contain sheets with the same names.
|
||||
*/
|
||||
public void copyUpdatedCells(Workbook workbook) {
|
||||
_sewb.copyUpdatedCells(workbook);
|
||||
}
|
||||
|
||||
/**
|
||||
* If cell contains a formula, the formula is evaluated and returned,
|
||||
* else the CellValue simply copies the appropriate cell value from
|
||||
* the cell and also its cell type. This method should be preferred over
|
||||
* evaluateInCell() when the call should not modify the contents of the
|
||||
* original cell.
|
||||
*
|
||||
* @param cell may be <code>null</code> signifying that the cell is not present (or blank)
|
||||
* @return <code>null</code> if the supplied cell is <code>null</code> or blank
|
||||
*/
|
||||
public ValueEval evaluate(String sheetName, int rowIndex, int columnIndex) {
|
||||
EvaluationCell cell = _sewb.getEvaluationCell(sheetName, rowIndex, columnIndex);
|
||||
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
return BoolEval.valueOf(cell.getBooleanCellValue());
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
return ErrorEval.valueOf(cell.getErrorCellValue());
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
return _evaluator.evaluate(cell);
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
return new NumberEval(cell.getNumericCellValue());
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
return new StringEval(cell.getStringCellValue());
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
return null;
|
||||
}
|
||||
throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
|
||||
}
|
||||
/**
|
||||
* Coordinates several formula evaluators together so that formulas that involve external
|
||||
* references can be evaluated.
|
||||
* @param workbookNames the simple file names used to identify the workbooks in formulas
|
||||
* with external links (for example "MyData.xls" as used in a formula "[MyData.xls]Sheet1!A1")
|
||||
* @param evaluators all evaluators for the full set of workbooks required by the formulas.
|
||||
*/
|
||||
public static void setupEnvironment(String[] workbookNames, ForkedEvaluator[] evaluators) {
|
||||
WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];
|
||||
for (int i = 0; i < wbEvals.length; i++) {
|
||||
wbEvals[i] = evaluators[i]._evaluator;
|
||||
}
|
||||
CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.eval.forked;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||
import org.apache.poi.ss.formula.IStabilityClassifier;
|
||||
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
|
||||
/**
|
||||
* An alternative workbook evaluator that saves memory in situations where a single workbook is
|
||||
* concurrently and independently evaluated many times. With standard formula evaluation, around
|
||||
* 90% of memory consumption is due to loading of the {@link HSSFWorkbook} or {@link org.apache.poi.xssf.usermodel.XSSFWorkbook}.
|
||||
* This class enables a 'master workbook' to be loaded just once and shared between many evaluation
|
||||
* clients. Each evaluation client creates its own {@link ForkedEvaluator} and can set cell values
|
||||
* that will be used for local evaluations (and don't disturb evaluations on other evaluators).
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ForkedEvaluator {
|
||||
|
||||
private WorkbookEvaluator _evaluator;
|
||||
private ForkedEvaluationWorkbook _sewb;
|
||||
|
||||
private ForkedEvaluator(EvaluationWorkbook masterWorkbook, IStabilityClassifier stabilityClassifier) {
|
||||
_sewb = new ForkedEvaluationWorkbook(masterWorkbook);
|
||||
_evaluator = new WorkbookEvaluator(_sewb, stabilityClassifier);
|
||||
}
|
||||
private static EvaluationWorkbook createEvaluationWorkbook(Workbook wb) {
|
||||
if (wb instanceof HSSFWorkbook) {
|
||||
return HSSFEvaluationWorkbook.create((HSSFWorkbook) wb);
|
||||
}
|
||||
// TODO rearrange POI build to allow this
|
||||
// if (wb instanceof XSSFWorkbook) {
|
||||
// return XSSFEvaluationWorkbook.create((XSSFWorkbook) wb);
|
||||
// }
|
||||
throw new IllegalArgumentException("Unexpected workbook type (" + wb.getClass().getName() + ")");
|
||||
}
|
||||
public static ForkedEvaluator create(Workbook wb, IStabilityClassifier stabilityClassifier) {
|
||||
return new ForkedEvaluator(createEvaluationWorkbook(wb), stabilityClassifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified cell to the supplied <tt>value</tt>
|
||||
* @param sheetName the name of the sheet containing the cell
|
||||
* @param rowIndex zero based
|
||||
* @param columnIndex zero based
|
||||
*/
|
||||
public void updateCell(String sheetName, int rowIndex, int columnIndex, ValueEval value) {
|
||||
|
||||
ForkedEvaluationCell cell = _sewb.getOrCreateUpdatableCell(sheetName, rowIndex, columnIndex);
|
||||
cell.setValue(value);
|
||||
_evaluator.notifyUpdateCell(cell);
|
||||
}
|
||||
/**
|
||||
* Copies the values of all updated cells (modified by calls to {@link
|
||||
* #updateCell(String, int, int, ValueEval)}) to the supplied <tt>workbook</tt>.<br/>
|
||||
* Typically, the supplied <tt>workbook</tt> is a writable copy of the 'master workbook',
|
||||
* but at the very least it must contain sheets with the same names.
|
||||
*/
|
||||
public void copyUpdatedCells(Workbook workbook) {
|
||||
_sewb.copyUpdatedCells(workbook);
|
||||
}
|
||||
|
||||
/**
|
||||
* If cell contains a formula, the formula is evaluated and returned,
|
||||
* else the CellValue simply copies the appropriate cell value from
|
||||
* the cell and also its cell type. This method should be preferred over
|
||||
* evaluateInCell() when the call should not modify the contents of the
|
||||
* original cell.
|
||||
*
|
||||
* @param cell may be <code>null</code> signifying that the cell is not present (or blank)
|
||||
* @return <code>null</code> if the supplied cell is <code>null</code> or blank
|
||||
*/
|
||||
public ValueEval evaluate(String sheetName, int rowIndex, int columnIndex) {
|
||||
EvaluationCell cell = _sewb.getEvaluationCell(sheetName, rowIndex, columnIndex);
|
||||
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
return BoolEval.valueOf(cell.getBooleanCellValue());
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
return ErrorEval.valueOf(cell.getErrorCellValue());
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
return _evaluator.evaluate(cell);
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
return new NumberEval(cell.getNumericCellValue());
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
return new StringEval(cell.getStringCellValue());
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
return null;
|
||||
}
|
||||
throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
|
||||
}
|
||||
/**
|
||||
* Coordinates several formula evaluators together so that formulas that involve external
|
||||
* references can be evaluated.
|
||||
* @param workbookNames the simple file names used to identify the workbooks in formulas
|
||||
* with external links (for example "MyData.xls" as used in a formula "[MyData.xls]Sheet1!A1")
|
||||
* @param evaluators all evaluators for the full set of workbooks required by the formulas.
|
||||
*/
|
||||
public static void setupEnvironment(String[] workbookNames, ForkedEvaluator[] evaluators) {
|
||||
WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];
|
||||
for (int i = 0; i < wbEvals.length; i++) {
|
||||
wbEvals[i] = evaluators[i]._evaluator;
|
||||
}
|
||||
CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);
|
||||
}
|
||||
}
|
||||
|
@ -1,114 +1,114 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
|
||||
/**
|
||||
* Mimics the 'data view' of a cell. This allows formula evaluator
|
||||
* to return a CellValue instead of precasting the value to String
|
||||
* or Number or boolean type.
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*/
|
||||
public final class CellValue {
|
||||
public static final CellValue TRUE = new CellValue(Cell.CELL_TYPE_BOOLEAN, 0.0, true, null, 0);
|
||||
public static final CellValue FALSE= new CellValue(Cell.CELL_TYPE_BOOLEAN, 0.0, false, null, 0);
|
||||
|
||||
private final int _cellType;
|
||||
private final double _numberValue;
|
||||
private final boolean _booleanValue;
|
||||
private final String _textValue;
|
||||
private final int _errorCode;
|
||||
|
||||
private CellValue(int cellType, double numberValue, boolean booleanValue,
|
||||
String textValue, int errorCode) {
|
||||
_cellType = cellType;
|
||||
_numberValue = numberValue;
|
||||
_booleanValue = booleanValue;
|
||||
_textValue = textValue;
|
||||
_errorCode = errorCode;
|
||||
}
|
||||
|
||||
|
||||
public CellValue(double numberValue) {
|
||||
this(Cell.CELL_TYPE_NUMERIC, numberValue, false, null, 0);
|
||||
}
|
||||
public static CellValue valueOf(boolean booleanValue) {
|
||||
return booleanValue ? TRUE : FALSE;
|
||||
}
|
||||
public CellValue(String stringValue) {
|
||||
this(Cell.CELL_TYPE_STRING, 0.0, false, stringValue, 0);
|
||||
}
|
||||
public static CellValue getError(int errorCode) {
|
||||
return new CellValue(Cell.CELL_TYPE_ERROR, 0.0, false, null, errorCode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the booleanValue.
|
||||
*/
|
||||
public boolean getBooleanValue() {
|
||||
return _booleanValue;
|
||||
}
|
||||
/**
|
||||
* @return Returns the numberValue.
|
||||
*/
|
||||
public double getNumberValue() {
|
||||
return _numberValue;
|
||||
}
|
||||
/**
|
||||
* @return Returns the stringValue.
|
||||
*/
|
||||
public String getStringValue() {
|
||||
return _textValue;
|
||||
}
|
||||
/**
|
||||
* @return Returns the cellType.
|
||||
*/
|
||||
public int getCellType() {
|
||||
return _cellType;
|
||||
}
|
||||
/**
|
||||
* @return Returns the errorValue.
|
||||
*/
|
||||
public byte getErrorValue() {
|
||||
return (byte) _errorCode;
|
||||
}
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append(formatAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String formatAsString() {
|
||||
switch (_cellType) {
|
||||
case Cell.CELL_TYPE_NUMERIC:
|
||||
return String.valueOf(_numberValue);
|
||||
case Cell.CELL_TYPE_STRING:
|
||||
return '"' + _textValue + '"';
|
||||
case Cell.CELL_TYPE_BOOLEAN:
|
||||
return _booleanValue ? "TRUE" : "FALSE";
|
||||
case Cell.CELL_TYPE_ERROR:
|
||||
return ErrorEval.getText(_errorCode);
|
||||
}
|
||||
return "<error unexpected cell type " + _cellType + ">";
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
|
||||
/**
|
||||
* Mimics the 'data view' of a cell. This allows formula evaluator
|
||||
* to return a CellValue instead of precasting the value to String
|
||||
* or Number or boolean type.
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*/
|
||||
public final class CellValue {
|
||||
public static final CellValue TRUE = new CellValue(Cell.CELL_TYPE_BOOLEAN, 0.0, true, null, 0);
|
||||
public static final CellValue FALSE= new CellValue(Cell.CELL_TYPE_BOOLEAN, 0.0, false, null, 0);
|
||||
|
||||
private final int _cellType;
|
||||
private final double _numberValue;
|
||||
private final boolean _booleanValue;
|
||||
private final String _textValue;
|
||||
private final int _errorCode;
|
||||
|
||||
private CellValue(int cellType, double numberValue, boolean booleanValue,
|
||||
String textValue, int errorCode) {
|
||||
_cellType = cellType;
|
||||
_numberValue = numberValue;
|
||||
_booleanValue = booleanValue;
|
||||
_textValue = textValue;
|
||||
_errorCode = errorCode;
|
||||
}
|
||||
|
||||
|
||||
public CellValue(double numberValue) {
|
||||
this(Cell.CELL_TYPE_NUMERIC, numberValue, false, null, 0);
|
||||
}
|
||||
public static CellValue valueOf(boolean booleanValue) {
|
||||
return booleanValue ? TRUE : FALSE;
|
||||
}
|
||||
public CellValue(String stringValue) {
|
||||
this(Cell.CELL_TYPE_STRING, 0.0, false, stringValue, 0);
|
||||
}
|
||||
public static CellValue getError(int errorCode) {
|
||||
return new CellValue(Cell.CELL_TYPE_ERROR, 0.0, false, null, errorCode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the booleanValue.
|
||||
*/
|
||||
public boolean getBooleanValue() {
|
||||
return _booleanValue;
|
||||
}
|
||||
/**
|
||||
* @return Returns the numberValue.
|
||||
*/
|
||||
public double getNumberValue() {
|
||||
return _numberValue;
|
||||
}
|
||||
/**
|
||||
* @return Returns the stringValue.
|
||||
*/
|
||||
public String getStringValue() {
|
||||
return _textValue;
|
||||
}
|
||||
/**
|
||||
* @return Returns the cellType.
|
||||
*/
|
||||
public int getCellType() {
|
||||
return _cellType;
|
||||
}
|
||||
/**
|
||||
* @return Returns the errorValue.
|
||||
*/
|
||||
public byte getErrorValue() {
|
||||
return (byte) _errorCode;
|
||||
}
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append(formatAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String formatAsString() {
|
||||
switch (_cellType) {
|
||||
case Cell.CELL_TYPE_NUMERIC:
|
||||
return String.valueOf(_numberValue);
|
||||
case Cell.CELL_TYPE_STRING:
|
||||
return '"' + _textValue + '"';
|
||||
case Cell.CELL_TYPE_BOOLEAN:
|
||||
return _booleanValue ? "TRUE" : "FALSE";
|
||||
case Cell.CELL_TYPE_ERROR:
|
||||
return ErrorEval.getText(_errorCode);
|
||||
}
|
||||
return "<error unexpected cell type " + _cellType + ">";
|
||||
}
|
||||
}
|
||||
|
@ -1,202 +1,202 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* A client anchor is attached to an excel worksheet. It anchors against a
|
||||
* top-left and bottom-right cell.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public interface ClientAnchor {
|
||||
/**
|
||||
* Move and Resize With Anchor Cells
|
||||
* <p>
|
||||
* Specifies that the current drawing shall move and
|
||||
* resize to maintain its row and column anchors (i.e. the
|
||||
* object is anchored to the actual from and to row and column)
|
||||
* </p>
|
||||
*/
|
||||
public static final int MOVE_AND_RESIZE = 0;
|
||||
|
||||
/**
|
||||
* Move With Cells but Do Not Resize
|
||||
* <p>
|
||||
* Specifies that the current drawing shall move with its
|
||||
* row and column (i.e. the object is anchored to the
|
||||
* actual from row and column), but that the size shall remain absolute.
|
||||
* </p>
|
||||
* <p>
|
||||
* If additional rows/columns are added between the from and to locations of the drawing,
|
||||
* the drawing shall move its to anchors as needed to maintain this same absolute size.
|
||||
* </p>
|
||||
*/
|
||||
public static final int MOVE_DONT_RESIZE = 2;
|
||||
|
||||
/**
|
||||
* Do Not Move or Resize With Underlying Rows/Columns
|
||||
* <p>
|
||||
* Specifies that the current start and end positions shall
|
||||
* be maintained with respect to the distances from the
|
||||
* absolute start point of the worksheet.
|
||||
* </p>
|
||||
* <p>
|
||||
* If additional rows/columns are added before the
|
||||
* drawing, the drawing shall move its anchors as needed
|
||||
* to maintain this same absolute position.
|
||||
* </p>
|
||||
*/
|
||||
public static final int DONT_MOVE_AND_RESIZE = 3;
|
||||
|
||||
/**
|
||||
* Returns the column (0 based) of the first cell.
|
||||
*
|
||||
* @return 0-based column of the first cell.
|
||||
*/
|
||||
public short getCol1();
|
||||
|
||||
/**
|
||||
* Sets the column (0 based) of the first cell.
|
||||
*
|
||||
* @param col1 0-based column of the first cell.
|
||||
*/
|
||||
public void setCol1(int col1);
|
||||
|
||||
/**
|
||||
* Returns the column (0 based) of the second cell.
|
||||
*
|
||||
* @return 0-based column of the second cell.
|
||||
*/
|
||||
public short getCol2();
|
||||
|
||||
/**
|
||||
* Returns the column (0 based) of the second cell.
|
||||
*
|
||||
* @param col2 0-based column of the second cell.
|
||||
*/
|
||||
public void setCol2(int col2);
|
||||
|
||||
/**
|
||||
* Returns the row (0 based) of the first cell.
|
||||
*
|
||||
* @return 0-based row of the first cell.
|
||||
*/
|
||||
public int getRow1();
|
||||
|
||||
/**
|
||||
* Returns the row (0 based) of the first cell.
|
||||
*
|
||||
* @param row1 0-based row of the first cell.
|
||||
*/
|
||||
public void setRow1(int row1);
|
||||
|
||||
/**
|
||||
* Returns the row (0 based) of the second cell.
|
||||
*
|
||||
* @return 0-based row of the second cell.
|
||||
*/
|
||||
public int getRow2();
|
||||
|
||||
/**
|
||||
* Returns the row (0 based) of the first cell.
|
||||
*
|
||||
* @param row2 0-based row of the first cell.
|
||||
*/
|
||||
public void setRow2(int row2);
|
||||
|
||||
/**
|
||||
* Returns the x coordinate within the first cell
|
||||
*
|
||||
* @return the x coordinate within the first cell
|
||||
*/
|
||||
public int getDx1();
|
||||
|
||||
/**
|
||||
* Sets the x coordinate within the first cell
|
||||
*
|
||||
* @param dx1 the x coordinate within the first cell
|
||||
*/
|
||||
public void setDx1(int dx1);
|
||||
|
||||
/**
|
||||
* Returns the y coordinate within the first cell
|
||||
*
|
||||
* @return the y coordinate within the first cell
|
||||
*/
|
||||
public int getDy1();
|
||||
|
||||
/**
|
||||
* Sets the y coordinate within the first cell
|
||||
*
|
||||
* @param dy1 the y coordinate within the first cell
|
||||
*/
|
||||
public void setDy1(int dy1);
|
||||
|
||||
/**
|
||||
* Sets the y coordinate within the second cell
|
||||
*
|
||||
* @return the y coordinate within the second cell
|
||||
*/
|
||||
public int getDy2();
|
||||
|
||||
/**
|
||||
* Sets the y coordinate within the second cell
|
||||
*
|
||||
* @param dy2 the y coordinate within the second cell
|
||||
*/
|
||||
public void setDy2(int dy2);
|
||||
|
||||
/**
|
||||
* Returns the x coordinate within the second cell
|
||||
*
|
||||
* @return the x coordinate within the second cell
|
||||
*/
|
||||
public int getDx2();
|
||||
|
||||
/**
|
||||
* Sets the x coordinate within the second cell
|
||||
*
|
||||
* @param dx2 the x coordinate within the second cell
|
||||
*/
|
||||
public void setDx2(int dx2);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the anchor type
|
||||
* <p>
|
||||
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
|
||||
* </p>
|
||||
* @param anchorType the anchor type
|
||||
* @see #MOVE_AND_RESIZE
|
||||
* @see #MOVE_DONT_RESIZE
|
||||
* @see #DONT_MOVE_AND_RESIZE
|
||||
*/
|
||||
public void setAnchorType( int anchorType );
|
||||
|
||||
/**
|
||||
* Gets the anchor type
|
||||
* <p>
|
||||
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
|
||||
* </p>
|
||||
* @return the anchor type
|
||||
* @see #MOVE_AND_RESIZE
|
||||
* @see #MOVE_DONT_RESIZE
|
||||
* @see #DONT_MOVE_AND_RESIZE
|
||||
*/
|
||||
public int getAnchorType();
|
||||
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* A client anchor is attached to an excel worksheet. It anchors against a
|
||||
* top-left and bottom-right cell.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public interface ClientAnchor {
|
||||
/**
|
||||
* Move and Resize With Anchor Cells
|
||||
* <p>
|
||||
* Specifies that the current drawing shall move and
|
||||
* resize to maintain its row and column anchors (i.e. the
|
||||
* object is anchored to the actual from and to row and column)
|
||||
* </p>
|
||||
*/
|
||||
public static final int MOVE_AND_RESIZE = 0;
|
||||
|
||||
/**
|
||||
* Move With Cells but Do Not Resize
|
||||
* <p>
|
||||
* Specifies that the current drawing shall move with its
|
||||
* row and column (i.e. the object is anchored to the
|
||||
* actual from row and column), but that the size shall remain absolute.
|
||||
* </p>
|
||||
* <p>
|
||||
* If additional rows/columns are added between the from and to locations of the drawing,
|
||||
* the drawing shall move its to anchors as needed to maintain this same absolute size.
|
||||
* </p>
|
||||
*/
|
||||
public static final int MOVE_DONT_RESIZE = 2;
|
||||
|
||||
/**
|
||||
* Do Not Move or Resize With Underlying Rows/Columns
|
||||
* <p>
|
||||
* Specifies that the current start and end positions shall
|
||||
* be maintained with respect to the distances from the
|
||||
* absolute start point of the worksheet.
|
||||
* </p>
|
||||
* <p>
|
||||
* If additional rows/columns are added before the
|
||||
* drawing, the drawing shall move its anchors as needed
|
||||
* to maintain this same absolute position.
|
||||
* </p>
|
||||
*/
|
||||
public static final int DONT_MOVE_AND_RESIZE = 3;
|
||||
|
||||
/**
|
||||
* Returns the column (0 based) of the first cell.
|
||||
*
|
||||
* @return 0-based column of the first cell.
|
||||
*/
|
||||
public short getCol1();
|
||||
|
||||
/**
|
||||
* Sets the column (0 based) of the first cell.
|
||||
*
|
||||
* @param col1 0-based column of the first cell.
|
||||
*/
|
||||
public void setCol1(int col1);
|
||||
|
||||
/**
|
||||
* Returns the column (0 based) of the second cell.
|
||||
*
|
||||
* @return 0-based column of the second cell.
|
||||
*/
|
||||
public short getCol2();
|
||||
|
||||
/**
|
||||
* Returns the column (0 based) of the second cell.
|
||||
*
|
||||
* @param col2 0-based column of the second cell.
|
||||
*/
|
||||
public void setCol2(int col2);
|
||||
|
||||
/**
|
||||
* Returns the row (0 based) of the first cell.
|
||||
*
|
||||
* @return 0-based row of the first cell.
|
||||
*/
|
||||
public int getRow1();
|
||||
|
||||
/**
|
||||
* Returns the row (0 based) of the first cell.
|
||||
*
|
||||
* @param row1 0-based row of the first cell.
|
||||
*/
|
||||
public void setRow1(int row1);
|
||||
|
||||
/**
|
||||
* Returns the row (0 based) of the second cell.
|
||||
*
|
||||
* @return 0-based row of the second cell.
|
||||
*/
|
||||
public int getRow2();
|
||||
|
||||
/**
|
||||
* Returns the row (0 based) of the first cell.
|
||||
*
|
||||
* @param row2 0-based row of the first cell.
|
||||
*/
|
||||
public void setRow2(int row2);
|
||||
|
||||
/**
|
||||
* Returns the x coordinate within the first cell
|
||||
*
|
||||
* @return the x coordinate within the first cell
|
||||
*/
|
||||
public int getDx1();
|
||||
|
||||
/**
|
||||
* Sets the x coordinate within the first cell
|
||||
*
|
||||
* @param dx1 the x coordinate within the first cell
|
||||
*/
|
||||
public void setDx1(int dx1);
|
||||
|
||||
/**
|
||||
* Returns the y coordinate within the first cell
|
||||
*
|
||||
* @return the y coordinate within the first cell
|
||||
*/
|
||||
public int getDy1();
|
||||
|
||||
/**
|
||||
* Sets the y coordinate within the first cell
|
||||
*
|
||||
* @param dy1 the y coordinate within the first cell
|
||||
*/
|
||||
public void setDy1(int dy1);
|
||||
|
||||
/**
|
||||
* Sets the y coordinate within the second cell
|
||||
*
|
||||
* @return the y coordinate within the second cell
|
||||
*/
|
||||
public int getDy2();
|
||||
|
||||
/**
|
||||
* Sets the y coordinate within the second cell
|
||||
*
|
||||
* @param dy2 the y coordinate within the second cell
|
||||
*/
|
||||
public void setDy2(int dy2);
|
||||
|
||||
/**
|
||||
* Returns the x coordinate within the second cell
|
||||
*
|
||||
* @return the x coordinate within the second cell
|
||||
*/
|
||||
public int getDx2();
|
||||
|
||||
/**
|
||||
* Sets the x coordinate within the second cell
|
||||
*
|
||||
* @param dx2 the x coordinate within the second cell
|
||||
*/
|
||||
public void setDx2(int dx2);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the anchor type
|
||||
* <p>
|
||||
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
|
||||
* </p>
|
||||
* @param anchorType the anchor type
|
||||
* @see #MOVE_AND_RESIZE
|
||||
* @see #MOVE_DONT_RESIZE
|
||||
* @see #DONT_MOVE_AND_RESIZE
|
||||
*/
|
||||
public void setAnchorType( int anchorType );
|
||||
|
||||
/**
|
||||
* Gets the anchor type
|
||||
* <p>
|
||||
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
|
||||
* </p>
|
||||
* @return the anchor type
|
||||
* @see #MOVE_AND_RESIZE
|
||||
* @see #MOVE_DONT_RESIZE
|
||||
* @see #DONT_MOVE_AND_RESIZE
|
||||
*/
|
||||
public int getAnchorType();
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,24 +1,24 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public interface Drawing {
|
||||
Picture createPicture(ClientAnchor anchor, int pictureIndex);
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public interface Drawing {
|
||||
Picture createPicture(ClientAnchor anchor, int pictureIndex);
|
||||
}
|
||||
|
@ -1,140 +1,140 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Enumerates error values in SpreadsheetML formula calculations.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public enum FormulaError {
|
||||
/**
|
||||
* Intended to indicate when two areas are required to intersect, but do not.
|
||||
* <p>Example:
|
||||
* In the case of SUM(B1 C1), the space between B1 and C1 is treated as the binary
|
||||
* intersection operator, when a comma was intended. end example]
|
||||
* </p>
|
||||
*/
|
||||
NULL(0x00, "#NULL!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when any number, including zero, is divided by zero.
|
||||
* Note: However, any error code divided by zero results in that error code.
|
||||
*/
|
||||
DIV0(0x07, "#DIV/0!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when an incompatible type argument is passed to a function, or
|
||||
* an incompatible type operand is used with an operator.
|
||||
* <p>Example:
|
||||
* In the case of a function argument, text was expected, but a number was provided
|
||||
* </p>
|
||||
*/
|
||||
VALUE(0x0F, "#VALUE!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when a cell reference is invalid.
|
||||
* <p>Example:
|
||||
* If a formula contains a reference to a cell, and then the row or column containing that cell is deleted,
|
||||
* a #REF! error results. If a worksheet does not support 20,001 columns,
|
||||
* OFFSET(A1,0,20000) will result in a #REF! error.
|
||||
* </p>
|
||||
*/
|
||||
REF(0x1D, "#REF!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when what looks like a name is used, but no such name has been defined.
|
||||
* <p>Example:
|
||||
* XYZ/3, where XYZ is not a defined name. Total is & A10,
|
||||
* where neither Total nor is is a defined name. Presumably, "Total is " & A10
|
||||
* was intended. SUM(A1C10), where the range A1:C10 was intended.
|
||||
* </p>
|
||||
*/
|
||||
NAME(0x1D, "#NAME?"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when an argument to a function has a compatible type, but has a
|
||||
* value that is outside the domain over which that function is defined. (This is known as
|
||||
* a domain error.)
|
||||
* <p>Example:
|
||||
* Certain calls to ASIN, ATANH, FACT, and SQRT might result in domain errors.
|
||||
* </p>
|
||||
* Intended to indicate that the result of a function cannot be represented in a value of
|
||||
* the specified type, typically due to extreme magnitude. (This is known as a range
|
||||
* error.)
|
||||
* <p>Example: FACT(1000) might result in a range error. </p>
|
||||
*/
|
||||
NUM(0x24, "#NUM!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when a designated value is not available.
|
||||
* <p>Example:
|
||||
* Some functions, such as SUMX2MY2, perform a series of operations on corresponding
|
||||
* elements in two arrays. If those arrays do not have the same number of elements, then
|
||||
* for some elements in the longer array, there are no corresponding elements in the
|
||||
* shorter one; that is, one or more values in the shorter array are not available.
|
||||
* </p>
|
||||
* This error value can be produced by calling the function NA
|
||||
*/
|
||||
NA(0x2A, "#N/A");
|
||||
|
||||
private byte type;
|
||||
private String repr;
|
||||
|
||||
private FormulaError(int type, String repr) {
|
||||
this.type = (byte) type;
|
||||
this.repr = repr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return numeric code of the error
|
||||
*/
|
||||
public byte getCode() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string representation of the error
|
||||
*/
|
||||
public String getString() {
|
||||
return repr;
|
||||
}
|
||||
|
||||
private static Map<String, FormulaError> smap = new HashMap<String, FormulaError>();
|
||||
private static Map<Byte, FormulaError> imap = new HashMap<Byte, FormulaError>();
|
||||
static{
|
||||
for (FormulaError error : values()) {
|
||||
imap.put(error.getCode(), error);
|
||||
smap.put(error.getString(), error);
|
||||
}
|
||||
}
|
||||
|
||||
public static FormulaError forInt(byte type){
|
||||
FormulaError err = imap.get(type);
|
||||
if(err == null) throw new IllegalArgumentException("Unknown error type: " + type);
|
||||
return err;
|
||||
}
|
||||
|
||||
public static FormulaError forString(String code){
|
||||
FormulaError err = smap.get(code);
|
||||
if(err == null) throw new IllegalArgumentException("Unknown error code: " + code);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Enumerates error values in SpreadsheetML formula calculations.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public enum FormulaError {
|
||||
/**
|
||||
* Intended to indicate when two areas are required to intersect, but do not.
|
||||
* <p>Example:
|
||||
* In the case of SUM(B1 C1), the space between B1 and C1 is treated as the binary
|
||||
* intersection operator, when a comma was intended. end example]
|
||||
* </p>
|
||||
*/
|
||||
NULL(0x00, "#NULL!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when any number, including zero, is divided by zero.
|
||||
* Note: However, any error code divided by zero results in that error code.
|
||||
*/
|
||||
DIV0(0x07, "#DIV/0!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when an incompatible type argument is passed to a function, or
|
||||
* an incompatible type operand is used with an operator.
|
||||
* <p>Example:
|
||||
* In the case of a function argument, text was expected, but a number was provided
|
||||
* </p>
|
||||
*/
|
||||
VALUE(0x0F, "#VALUE!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when a cell reference is invalid.
|
||||
* <p>Example:
|
||||
* If a formula contains a reference to a cell, and then the row or column containing that cell is deleted,
|
||||
* a #REF! error results. If a worksheet does not support 20,001 columns,
|
||||
* OFFSET(A1,0,20000) will result in a #REF! error.
|
||||
* </p>
|
||||
*/
|
||||
REF(0x1D, "#REF!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when what looks like a name is used, but no such name has been defined.
|
||||
* <p>Example:
|
||||
* XYZ/3, where XYZ is not a defined name. Total is & A10,
|
||||
* where neither Total nor is is a defined name. Presumably, "Total is " & A10
|
||||
* was intended. SUM(A1C10), where the range A1:C10 was intended.
|
||||
* </p>
|
||||
*/
|
||||
NAME(0x1D, "#NAME?"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when an argument to a function has a compatible type, but has a
|
||||
* value that is outside the domain over which that function is defined. (This is known as
|
||||
* a domain error.)
|
||||
* <p>Example:
|
||||
* Certain calls to ASIN, ATANH, FACT, and SQRT might result in domain errors.
|
||||
* </p>
|
||||
* Intended to indicate that the result of a function cannot be represented in a value of
|
||||
* the specified type, typically due to extreme magnitude. (This is known as a range
|
||||
* error.)
|
||||
* <p>Example: FACT(1000) might result in a range error. </p>
|
||||
*/
|
||||
NUM(0x24, "#NUM!"),
|
||||
|
||||
/**
|
||||
* Intended to indicate when a designated value is not available.
|
||||
* <p>Example:
|
||||
* Some functions, such as SUMX2MY2, perform a series of operations on corresponding
|
||||
* elements in two arrays. If those arrays do not have the same number of elements, then
|
||||
* for some elements in the longer array, there are no corresponding elements in the
|
||||
* shorter one; that is, one or more values in the shorter array are not available.
|
||||
* </p>
|
||||
* This error value can be produced by calling the function NA
|
||||
*/
|
||||
NA(0x2A, "#N/A");
|
||||
|
||||
private byte type;
|
||||
private String repr;
|
||||
|
||||
private FormulaError(int type, String repr) {
|
||||
this.type = (byte) type;
|
||||
this.repr = repr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return numeric code of the error
|
||||
*/
|
||||
public byte getCode() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string representation of the error
|
||||
*/
|
||||
public String getString() {
|
||||
return repr;
|
||||
}
|
||||
|
||||
private static Map<String, FormulaError> smap = new HashMap<String, FormulaError>();
|
||||
private static Map<Byte, FormulaError> imap = new HashMap<Byte, FormulaError>();
|
||||
static{
|
||||
for (FormulaError error : values()) {
|
||||
imap.put(error.getCode(), error);
|
||||
smap.put(error.getString(), error);
|
||||
}
|
||||
}
|
||||
|
||||
public static FormulaError forInt(byte type){
|
||||
FormulaError err = imap.get(type);
|
||||
if(err == null) throw new IllegalArgumentException("Unknown error type: " + type);
|
||||
return err;
|
||||
}
|
||||
|
||||
public static FormulaError forString(String code){
|
||||
FormulaError err = smap.get(code);
|
||||
if(err == null) throw new IllegalArgumentException("Unknown error code: " + code);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
@ -1,95 +1,95 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* The enumeration value indicating horizontal alignment of a cell,
|
||||
* i.e., whether it is aligned general, left, right, horizontally centered, filled (replicated),
|
||||
* justified, centered across multiple cells, or distributed.
|
||||
*/
|
||||
public enum HorizontalAlignment {
|
||||
/**
|
||||
* The horizontal alignment is general-aligned. Text data is left-aligned.
|
||||
* Numbers, dates, and times are rightaligned. Boolean types are centered.
|
||||
* Changing the alignment does not change the type of data.
|
||||
*/
|
||||
GENERAL,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is left-aligned, even in Rightto-Left mode.
|
||||
* Aligns contents at the left edge of the cell. If an indent amount is specified, the contents of
|
||||
* the cell is indented from the left by the specified number of character spaces. The character spaces are
|
||||
* based on the default font and font size for the workbook.
|
||||
*/
|
||||
LEFT,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is centered, meaning the text is centered across the cell.
|
||||
*/
|
||||
CENTER,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is right-aligned, meaning that cell contents are aligned at the right edge of the cell,
|
||||
* even in Right-to-Left mode.
|
||||
*/
|
||||
RIGHT,
|
||||
|
||||
/**
|
||||
* Indicates that the value of the cell should be filled
|
||||
* across the entire width of the cell. If blank cells to the right also have the fill alignment,
|
||||
* they are also filled with the value, using a convention similar to centerContinuous.
|
||||
* <p>
|
||||
* Additional rules:
|
||||
* <ol>
|
||||
* <li>Only whole values can be appended, not partial values.</li>
|
||||
* <li>The column will not be widened to 'best fit' the filled value</li>
|
||||
* <li>If appending an additional occurrence of the value exceeds the boundary of the cell
|
||||
* left/right edge, don't append the additional occurrence of the value.</li>
|
||||
* <li>The display value of the cell is filled, not the underlying raw number.</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
*/
|
||||
FILL,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is justified (flush left and right).
|
||||
* For each line of text, aligns each line of the wrapped text in a cell to the right and left
|
||||
* (except the last line). If no single line of text wraps in the cell, then the text is not justified.
|
||||
*/
|
||||
JUSTIFY,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is centered across multiple cells.
|
||||
* The information about how many cells to span is expressed in the Sheet Part,
|
||||
* in the row of the cell in question. For each cell that is spanned in the alignment,
|
||||
* a cell element needs to be written out, with the same style Id which references the centerContinuous alignment.
|
||||
*/
|
||||
CENTER_SELECTION,
|
||||
|
||||
/**
|
||||
* Indicates that each 'word' in each line of text inside the cell is evenly distributed
|
||||
* across the width of the cell, with flush right and left margins.
|
||||
* <p>
|
||||
* When there is also an indent value to apply, both the left and right side of the cell
|
||||
* are padded by the indent value.
|
||||
* </p>
|
||||
* <p> A 'word' is a set of characters with no space character in them. </p>
|
||||
* <p> Two lines inside a cell are separated by a carriage return. </p>
|
||||
*/
|
||||
DISTRIBUTED
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* The enumeration value indicating horizontal alignment of a cell,
|
||||
* i.e., whether it is aligned general, left, right, horizontally centered, filled (replicated),
|
||||
* justified, centered across multiple cells, or distributed.
|
||||
*/
|
||||
public enum HorizontalAlignment {
|
||||
/**
|
||||
* The horizontal alignment is general-aligned. Text data is left-aligned.
|
||||
* Numbers, dates, and times are rightaligned. Boolean types are centered.
|
||||
* Changing the alignment does not change the type of data.
|
||||
*/
|
||||
GENERAL,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is left-aligned, even in Rightto-Left mode.
|
||||
* Aligns contents at the left edge of the cell. If an indent amount is specified, the contents of
|
||||
* the cell is indented from the left by the specified number of character spaces. The character spaces are
|
||||
* based on the default font and font size for the workbook.
|
||||
*/
|
||||
LEFT,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is centered, meaning the text is centered across the cell.
|
||||
*/
|
||||
CENTER,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is right-aligned, meaning that cell contents are aligned at the right edge of the cell,
|
||||
* even in Right-to-Left mode.
|
||||
*/
|
||||
RIGHT,
|
||||
|
||||
/**
|
||||
* Indicates that the value of the cell should be filled
|
||||
* across the entire width of the cell. If blank cells to the right also have the fill alignment,
|
||||
* they are also filled with the value, using a convention similar to centerContinuous.
|
||||
* <p>
|
||||
* Additional rules:
|
||||
* <ol>
|
||||
* <li>Only whole values can be appended, not partial values.</li>
|
||||
* <li>The column will not be widened to 'best fit' the filled value</li>
|
||||
* <li>If appending an additional occurrence of the value exceeds the boundary of the cell
|
||||
* left/right edge, don't append the additional occurrence of the value.</li>
|
||||
* <li>The display value of the cell is filled, not the underlying raw number.</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
*/
|
||||
FILL,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is justified (flush left and right).
|
||||
* For each line of text, aligns each line of the wrapped text in a cell to the right and left
|
||||
* (except the last line). If no single line of text wraps in the cell, then the text is not justified.
|
||||
*/
|
||||
JUSTIFY,
|
||||
|
||||
/**
|
||||
* The horizontal alignment is centered across multiple cells.
|
||||
* The information about how many cells to span is expressed in the Sheet Part,
|
||||
* in the row of the cell in question. For each cell that is spanned in the alignment,
|
||||
* a cell element needs to be written out, with the same style Id which references the centerContinuous alignment.
|
||||
*/
|
||||
CENTER_SELECTION,
|
||||
|
||||
/**
|
||||
* Indicates that each 'word' in each line of text inside the cell is evenly distributed
|
||||
* across the width of the cell, with flush right and left margins.
|
||||
* <p>
|
||||
* When there is also an indent value to apply, both the left and right side of the cell
|
||||
* are padded by the indent value.
|
||||
* </p>
|
||||
* <p> A 'word' is a set of characters with no space character in them. </p>
|
||||
* <p> Two lines inside a cell are separated by a carriage return. </p>
|
||||
*/
|
||||
DISTRIBUTED
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* Repersents a picture in a SpreadsheetML document
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public interface Picture {
|
||||
|
||||
/**
|
||||
* Reset the image to the original size.
|
||||
*/
|
||||
void resize();
|
||||
|
||||
/**
|
||||
* Reset the image to the original size.
|
||||
*
|
||||
* @param scale the amount by which image dimensions are multiplied relative to the original size.
|
||||
* <code>resize(1.0)</code> sets the original size, <code>resize(0.5)</code> resize to 50% of the original,
|
||||
* <code>resize(2.0)</code> resizes to 200% of the original.
|
||||
*/
|
||||
void resize(double scale);
|
||||
|
||||
ClientAnchor getPreferredSize();
|
||||
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* Repersents a picture in a SpreadsheetML document
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public interface Picture {
|
||||
|
||||
/**
|
||||
* Reset the image to the original size.
|
||||
*/
|
||||
void resize();
|
||||
|
||||
/**
|
||||
* Reset the image to the original size.
|
||||
*
|
||||
* @param scale the amount by which image dimensions are multiplied relative to the original size.
|
||||
* <code>resize(1.0)</code> sets the original size, <code>resize(0.5)</code> resize to 50% of the original,
|
||||
* <code>resize(2.0)</code> resizes to 200% of the original.
|
||||
*/
|
||||
void resize(double scale);
|
||||
|
||||
ClientAnchor getPreferredSize();
|
||||
|
||||
}
|
||||
|
@ -1,212 +1,212 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* All known types of automatic shapes in DrawingML
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class ShapeTypes {
|
||||
public static final int LINE = 1;
|
||||
public static final int LINE_INV = 2;
|
||||
public static final int TRIANGLE = 3;
|
||||
public static final int RT_TRIANGLE = 4;
|
||||
public static final int RECT = 5;
|
||||
public static final int DIAMOND = 6;
|
||||
public static final int PARALLELOGRAM = 7;
|
||||
public static final int TRAPEZOID = 8;
|
||||
public static final int NON_ISOSCELES_TRAPEZOID = 9;
|
||||
public static final int PENTAGON = 10;
|
||||
public static final int HEXAGON = 11;
|
||||
public static final int HEPTAGON = 12;
|
||||
public static final int OCTAGON = 13;
|
||||
public static final int DECAGON = 14;
|
||||
public static final int DODECAGON = 15;
|
||||
public static final int STAR_4 = 16;
|
||||
public static final int STAR_5 = 17;
|
||||
public static final int STAR_6 = 18;
|
||||
public static final int STAR_7 = 19;
|
||||
public static final int STAR_8 = 20;
|
||||
public static final int STAR_10 = 21;
|
||||
public static final int STAR_12 = 22;
|
||||
public static final int STAR_16 = 23;
|
||||
public static final int STAR_24 = 24;
|
||||
public static final int STAR_32 = 25;
|
||||
public static final int ROUND_RECT = 26;
|
||||
public static final int ROUND_1_RECT = 27;
|
||||
public static final int ROUND_2_SAME_RECT = 28;
|
||||
public static final int ROUND_2_DIAG_RECT = 29;
|
||||
public static final int SNIP_ROUND_RECT = 30;
|
||||
public static final int SNIP_1_RECT = 31;
|
||||
public static final int SNIP_2_SAME_RECT = 32;
|
||||
public static final int SNIP_2_DIAG_RECT = 33;
|
||||
public static final int PLAQUE = 34;
|
||||
public static final int ELLIPSE = 35;
|
||||
public static final int TEARDROP = 36;
|
||||
public static final int HOME_PLATE = 37;
|
||||
public static final int CHEVRON = 38;
|
||||
public static final int PIE_WEDGE = 39;
|
||||
public static final int PIE = 40;
|
||||
public static final int BLOCK_ARC = 41;
|
||||
public static final int DONUT = 42;
|
||||
public static final int NO_SMOKING = 43;
|
||||
public static final int RIGHT_ARROW = 44;
|
||||
public static final int LEFT_ARROW = 45;
|
||||
public static final int UP_ARROW = 46;
|
||||
public static final int DOWN_ARROW = 47;
|
||||
public static final int STRIPED_RIGHT_ARROW = 48;
|
||||
public static final int NOTCHED_RIGHT_ARROW = 49;
|
||||
public static final int BENT_UP_ARROW = 50;
|
||||
public static final int LEFT_RIGHT_ARROW = 51;
|
||||
public static final int UP_DOWN_ARROW = 52;
|
||||
public static final int LEFT_UP_ARROW = 53;
|
||||
public static final int LEFT_RIGHT_UP_ARROW = 54;
|
||||
public static final int QUAD_ARROW = 55;
|
||||
public static final int LEFT_ARROW_CALLOUT = 56;
|
||||
public static final int RIGHT_ARROW_CALLOUT = 57;
|
||||
public static final int UP_ARROW_CALLOUT = 58;
|
||||
public static final int DOWN_ARROW_CALLOUT = 59;
|
||||
public static final int LEFT_RIGHT_ARROW_CALLOUT = 60;
|
||||
public static final int UP_DOWN_ARROW_CALLOUT = 61;
|
||||
public static final int QUAD_ARROW_CALLOUT = 62;
|
||||
public static final int BENT_ARROW = 63;
|
||||
public static final int UTURN_ARROW = 64;
|
||||
public static final int CIRCULAR_ARROW = 65;
|
||||
public static final int LEFT_CIRCULAR_ARROW = 66;
|
||||
public static final int LEFT_RIGHT_CIRCULAR_ARROW = 67;
|
||||
public static final int CURVED_RIGHT_ARROW = 68;
|
||||
public static final int CURVED_LEFT_ARROW = 69;
|
||||
public static final int CURVED_UP_ARROW = 70;
|
||||
public static final int CURVED_DOWN_ARROW = 71;
|
||||
public static final int SWOOSH_ARROW = 72;
|
||||
public static final int CUBE = 73;
|
||||
public static final int CAN = 74;
|
||||
public static final int LIGHTNING_BOLT = 75;
|
||||
public static final int HEART = 76;
|
||||
public static final int SUN = 77;
|
||||
public static final int MOON = 78;
|
||||
public static final int SMILEY_FACE = 79;
|
||||
public static final int IRREGULAR_SEAL_1 = 80;
|
||||
public static final int IRREGULAR_SEAL_2 = 81;
|
||||
public static final int FOLDED_CORNER = 82;
|
||||
public static final int BEVEL = 83;
|
||||
public static final int FRAME = 84;
|
||||
public static final int HALF_FRAME = 85;
|
||||
public static final int CORNER = 86;
|
||||
public static final int DIAG_STRIPE = 87;
|
||||
public static final int CHORD = 88;
|
||||
public static final int ARC = 89;
|
||||
public static final int LEFT_BRACKET = 90;
|
||||
public static final int RIGHT_BRACKET = 91;
|
||||
public static final int LEFT_BRACE = 92;
|
||||
public static final int RIGHT_BRACE = 93;
|
||||
public static final int BRACKET_PAIR = 94;
|
||||
public static final int BRACE_PAIR = 95;
|
||||
public static final int STRAIGHT_CONNECTOR_1 = 96;
|
||||
public static final int BENT_CONNECTOR_2 = 97;
|
||||
public static final int BENT_CONNECTOR_3 = 98;
|
||||
public static final int BENT_CONNECTOR_4 = 99;
|
||||
public static final int BENT_CONNECTOR_5 = 100;
|
||||
public static final int CURVED_CONNECTOR_2 = 101;
|
||||
public static final int CURVED_CONNECTOR_3 = 102;
|
||||
public static final int CURVED_CONNECTOR_4 = 103;
|
||||
public static final int CURVED_CONNECTOR_5 = 104;
|
||||
public static final int CALLOUT_1 = 105;
|
||||
public static final int CALLOUT_2 = 106;
|
||||
public static final int CALLOUT_3 = 107;
|
||||
public static final int ACCENT_CALLOUT_1 = 108;
|
||||
public static final int ACCENT_CALLOUT_2 = 109;
|
||||
public static final int ACCENT_CALLOUT_3 = 110;
|
||||
public static final int BORDER_CALLOUT_1 = 111;
|
||||
public static final int BORDER_CALLOUT_2 = 112;
|
||||
public static final int BORDER_CALLOUT_3 = 113;
|
||||
public static final int ACCENT_BORDER_CALLOUT_1 = 114;
|
||||
public static final int ACCENT_BORDER_CALLOUT_2 = 115;
|
||||
public static final int ACCENT_BORDER_CALLOUT_3 = 116;
|
||||
public static final int WEDGE_RECT_CALLOUT = 117;
|
||||
public static final int WEDGE_ROUND_RECT_CALLOUT = 118;
|
||||
public static final int WEDGE_ELLIPSE_CALLOUT = 119;
|
||||
public static final int CLOUD_CALLOUT = 120;
|
||||
public static final int CLOUD = 121;
|
||||
public static final int RIBBON = 122;
|
||||
public static final int RIBBON_2 = 123;
|
||||
public static final int ELLIPSE_RIBBON = 124;
|
||||
public static final int ELLIPSE_RIBBON_2 = 125;
|
||||
public static final int LEFT_RIGHT_RIBBON = 126;
|
||||
public static final int VERTICAL_SCROLL = 127;
|
||||
public static final int HORIZONTAL_SCROLL = 128;
|
||||
public static final int WAVE = 129;
|
||||
public static final int DOUBLE_WAVE = 130;
|
||||
public static final int PLUS = 131;
|
||||
public static final int FLOW_CHART_PROCESS = 132;
|
||||
public static final int FLOW_CHART_DECISION = 133;
|
||||
public static final int FLOW_CHART_INPUT_OUTPUT = 134;
|
||||
public static final int FLOW_CHART_PREDEFINED_PROCESS = 135;
|
||||
public static final int FLOW_CHART_INTERNAL_STORAGE = 136;
|
||||
public static final int FLOW_CHART_DOCUMENT = 137;
|
||||
public static final int FLOW_CHART_MULTIDOCUMENT = 138;
|
||||
public static final int FLOW_CHART_TERMINATOR = 139;
|
||||
public static final int FLOW_CHART_PREPARATION = 140;
|
||||
public static final int FLOW_CHART_MANUAL_INPUT = 141;
|
||||
public static final int FLOW_CHART_MANUAL_OPERATION = 142;
|
||||
public static final int FLOW_CHART_CONNECTOR = 143;
|
||||
public static final int FLOW_CHART_PUNCHED_CARD = 144;
|
||||
public static final int FLOW_CHART_PUNCHED_TAPE = 145;
|
||||
public static final int FLOW_CHART_SUMMING_JUNCTION = 146;
|
||||
public static final int FLOW_CHART_OR = 147;
|
||||
public static final int FLOW_CHART_COLLATE = 148;
|
||||
public static final int FLOW_CHART_SORT = 149;
|
||||
public static final int FLOW_CHART_EXTRACT = 150;
|
||||
public static final int FLOW_CHART_MERGE = 151;
|
||||
public static final int FLOW_CHART_OFFLINE_STORAGE = 152;
|
||||
public static final int FLOW_CHART_ONLINE_STORAGE = 153;
|
||||
public static final int FLOW_CHART_MAGNETIC_TAPE = 154;
|
||||
public static final int FLOW_CHART_MAGNETIC_DISK = 155;
|
||||
public static final int FLOW_CHART_MAGNETIC_DRUM = 156;
|
||||
public static final int FLOW_CHART_DISPLAY = 157;
|
||||
public static final int FLOW_CHART_DELAY = 158;
|
||||
public static final int FLOW_CHART_ALTERNATE_PROCESS = 159;
|
||||
public static final int FLOW_CHART_OFFPAGE_CONNECTOR = 160;
|
||||
public static final int ACTION_BUTTON_BLANK = 161;
|
||||
public static final int ACTION_BUTTON_HOME = 162;
|
||||
public static final int ACTION_BUTTON_HELP = 163;
|
||||
public static final int ACTION_BUTTON_INFORMATION = 164;
|
||||
public static final int ACTION_BUTTON_FORWARD_NEXT = 165;
|
||||
public static final int ACTION_BUTTON_BACK_PREVIOUS = 166;
|
||||
public static final int ACTION_BUTTON_END = 167;
|
||||
public static final int ACTION_BUTTON_BEGINNING = 168;
|
||||
public static final int ACTION_BUTTON_RETURN = 169;
|
||||
public static final int ACTION_BUTTON_DOCUMENT = 170;
|
||||
public static final int ACTION_BUTTON_SOUND = 171;
|
||||
public static final int ACTION_BUTTON_MOVIE = 172;
|
||||
public static final int GEAR_6 = 173;
|
||||
public static final int GEAR_9 = 174;
|
||||
public static final int FUNNEL = 175;
|
||||
public static final int MATH_PLUS = 176;
|
||||
public static final int MATH_MINUS = 177;
|
||||
public static final int MATH_MULTIPLY = 178;
|
||||
public static final int MATH_DIVIDE = 179;
|
||||
public static final int MATH_EQUAL = 180;
|
||||
public static final int MATH_NOT_EQUAL = 181;
|
||||
public static final int CORNER_TABS = 182;
|
||||
public static final int SQUARE_TABS = 183;
|
||||
public static final int PLAQUE_TABS = 184;
|
||||
public static final int CHART_X = 185;
|
||||
public static final int CHART_STAR = 186;
|
||||
public static final int CHART_PLUS = 187;
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* All known types of automatic shapes in DrawingML
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class ShapeTypes {
|
||||
public static final int LINE = 1;
|
||||
public static final int LINE_INV = 2;
|
||||
public static final int TRIANGLE = 3;
|
||||
public static final int RT_TRIANGLE = 4;
|
||||
public static final int RECT = 5;
|
||||
public static final int DIAMOND = 6;
|
||||
public static final int PARALLELOGRAM = 7;
|
||||
public static final int TRAPEZOID = 8;
|
||||
public static final int NON_ISOSCELES_TRAPEZOID = 9;
|
||||
public static final int PENTAGON = 10;
|
||||
public static final int HEXAGON = 11;
|
||||
public static final int HEPTAGON = 12;
|
||||
public static final int OCTAGON = 13;
|
||||
public static final int DECAGON = 14;
|
||||
public static final int DODECAGON = 15;
|
||||
public static final int STAR_4 = 16;
|
||||
public static final int STAR_5 = 17;
|
||||
public static final int STAR_6 = 18;
|
||||
public static final int STAR_7 = 19;
|
||||
public static final int STAR_8 = 20;
|
||||
public static final int STAR_10 = 21;
|
||||
public static final int STAR_12 = 22;
|
||||
public static final int STAR_16 = 23;
|
||||
public static final int STAR_24 = 24;
|
||||
public static final int STAR_32 = 25;
|
||||
public static final int ROUND_RECT = 26;
|
||||
public static final int ROUND_1_RECT = 27;
|
||||
public static final int ROUND_2_SAME_RECT = 28;
|
||||
public static final int ROUND_2_DIAG_RECT = 29;
|
||||
public static final int SNIP_ROUND_RECT = 30;
|
||||
public static final int SNIP_1_RECT = 31;
|
||||
public static final int SNIP_2_SAME_RECT = 32;
|
||||
public static final int SNIP_2_DIAG_RECT = 33;
|
||||
public static final int PLAQUE = 34;
|
||||
public static final int ELLIPSE = 35;
|
||||
public static final int TEARDROP = 36;
|
||||
public static final int HOME_PLATE = 37;
|
||||
public static final int CHEVRON = 38;
|
||||
public static final int PIE_WEDGE = 39;
|
||||
public static final int PIE = 40;
|
||||
public static final int BLOCK_ARC = 41;
|
||||
public static final int DONUT = 42;
|
||||
public static final int NO_SMOKING = 43;
|
||||
public static final int RIGHT_ARROW = 44;
|
||||
public static final int LEFT_ARROW = 45;
|
||||
public static final int UP_ARROW = 46;
|
||||
public static final int DOWN_ARROW = 47;
|
||||
public static final int STRIPED_RIGHT_ARROW = 48;
|
||||
public static final int NOTCHED_RIGHT_ARROW = 49;
|
||||
public static final int BENT_UP_ARROW = 50;
|
||||
public static final int LEFT_RIGHT_ARROW = 51;
|
||||
public static final int UP_DOWN_ARROW = 52;
|
||||
public static final int LEFT_UP_ARROW = 53;
|
||||
public static final int LEFT_RIGHT_UP_ARROW = 54;
|
||||
public static final int QUAD_ARROW = 55;
|
||||
public static final int LEFT_ARROW_CALLOUT = 56;
|
||||
public static final int RIGHT_ARROW_CALLOUT = 57;
|
||||
public static final int UP_ARROW_CALLOUT = 58;
|
||||
public static final int DOWN_ARROW_CALLOUT = 59;
|
||||
public static final int LEFT_RIGHT_ARROW_CALLOUT = 60;
|
||||
public static final int UP_DOWN_ARROW_CALLOUT = 61;
|
||||
public static final int QUAD_ARROW_CALLOUT = 62;
|
||||
public static final int BENT_ARROW = 63;
|
||||
public static final int UTURN_ARROW = 64;
|
||||
public static final int CIRCULAR_ARROW = 65;
|
||||
public static final int LEFT_CIRCULAR_ARROW = 66;
|
||||
public static final int LEFT_RIGHT_CIRCULAR_ARROW = 67;
|
||||
public static final int CURVED_RIGHT_ARROW = 68;
|
||||
public static final int CURVED_LEFT_ARROW = 69;
|
||||
public static final int CURVED_UP_ARROW = 70;
|
||||
public static final int CURVED_DOWN_ARROW = 71;
|
||||
public static final int SWOOSH_ARROW = 72;
|
||||
public static final int CUBE = 73;
|
||||
public static final int CAN = 74;
|
||||
public static final int LIGHTNING_BOLT = 75;
|
||||
public static final int HEART = 76;
|
||||
public static final int SUN = 77;
|
||||
public static final int MOON = 78;
|
||||
public static final int SMILEY_FACE = 79;
|
||||
public static final int IRREGULAR_SEAL_1 = 80;
|
||||
public static final int IRREGULAR_SEAL_2 = 81;
|
||||
public static final int FOLDED_CORNER = 82;
|
||||
public static final int BEVEL = 83;
|
||||
public static final int FRAME = 84;
|
||||
public static final int HALF_FRAME = 85;
|
||||
public static final int CORNER = 86;
|
||||
public static final int DIAG_STRIPE = 87;
|
||||
public static final int CHORD = 88;
|
||||
public static final int ARC = 89;
|
||||
public static final int LEFT_BRACKET = 90;
|
||||
public static final int RIGHT_BRACKET = 91;
|
||||
public static final int LEFT_BRACE = 92;
|
||||
public static final int RIGHT_BRACE = 93;
|
||||
public static final int BRACKET_PAIR = 94;
|
||||
public static final int BRACE_PAIR = 95;
|
||||
public static final int STRAIGHT_CONNECTOR_1 = 96;
|
||||
public static final int BENT_CONNECTOR_2 = 97;
|
||||
public static final int BENT_CONNECTOR_3 = 98;
|
||||
public static final int BENT_CONNECTOR_4 = 99;
|
||||
public static final int BENT_CONNECTOR_5 = 100;
|
||||
public static final int CURVED_CONNECTOR_2 = 101;
|
||||
public static final int CURVED_CONNECTOR_3 = 102;
|
||||
public static final int CURVED_CONNECTOR_4 = 103;
|
||||
public static final int CURVED_CONNECTOR_5 = 104;
|
||||
public static final int CALLOUT_1 = 105;
|
||||
public static final int CALLOUT_2 = 106;
|
||||
public static final int CALLOUT_3 = 107;
|
||||
public static final int ACCENT_CALLOUT_1 = 108;
|
||||
public static final int ACCENT_CALLOUT_2 = 109;
|
||||
public static final int ACCENT_CALLOUT_3 = 110;
|
||||
public static final int BORDER_CALLOUT_1 = 111;
|
||||
public static final int BORDER_CALLOUT_2 = 112;
|
||||
public static final int BORDER_CALLOUT_3 = 113;
|
||||
public static final int ACCENT_BORDER_CALLOUT_1 = 114;
|
||||
public static final int ACCENT_BORDER_CALLOUT_2 = 115;
|
||||
public static final int ACCENT_BORDER_CALLOUT_3 = 116;
|
||||
public static final int WEDGE_RECT_CALLOUT = 117;
|
||||
public static final int WEDGE_ROUND_RECT_CALLOUT = 118;
|
||||
public static final int WEDGE_ELLIPSE_CALLOUT = 119;
|
||||
public static final int CLOUD_CALLOUT = 120;
|
||||
public static final int CLOUD = 121;
|
||||
public static final int RIBBON = 122;
|
||||
public static final int RIBBON_2 = 123;
|
||||
public static final int ELLIPSE_RIBBON = 124;
|
||||
public static final int ELLIPSE_RIBBON_2 = 125;
|
||||
public static final int LEFT_RIGHT_RIBBON = 126;
|
||||
public static final int VERTICAL_SCROLL = 127;
|
||||
public static final int HORIZONTAL_SCROLL = 128;
|
||||
public static final int WAVE = 129;
|
||||
public static final int DOUBLE_WAVE = 130;
|
||||
public static final int PLUS = 131;
|
||||
public static final int FLOW_CHART_PROCESS = 132;
|
||||
public static final int FLOW_CHART_DECISION = 133;
|
||||
public static final int FLOW_CHART_INPUT_OUTPUT = 134;
|
||||
public static final int FLOW_CHART_PREDEFINED_PROCESS = 135;
|
||||
public static final int FLOW_CHART_INTERNAL_STORAGE = 136;
|
||||
public static final int FLOW_CHART_DOCUMENT = 137;
|
||||
public static final int FLOW_CHART_MULTIDOCUMENT = 138;
|
||||
public static final int FLOW_CHART_TERMINATOR = 139;
|
||||
public static final int FLOW_CHART_PREPARATION = 140;
|
||||
public static final int FLOW_CHART_MANUAL_INPUT = 141;
|
||||
public static final int FLOW_CHART_MANUAL_OPERATION = 142;
|
||||
public static final int FLOW_CHART_CONNECTOR = 143;
|
||||
public static final int FLOW_CHART_PUNCHED_CARD = 144;
|
||||
public static final int FLOW_CHART_PUNCHED_TAPE = 145;
|
||||
public static final int FLOW_CHART_SUMMING_JUNCTION = 146;
|
||||
public static final int FLOW_CHART_OR = 147;
|
||||
public static final int FLOW_CHART_COLLATE = 148;
|
||||
public static final int FLOW_CHART_SORT = 149;
|
||||
public static final int FLOW_CHART_EXTRACT = 150;
|
||||
public static final int FLOW_CHART_MERGE = 151;
|
||||
public static final int FLOW_CHART_OFFLINE_STORAGE = 152;
|
||||
public static final int FLOW_CHART_ONLINE_STORAGE = 153;
|
||||
public static final int FLOW_CHART_MAGNETIC_TAPE = 154;
|
||||
public static final int FLOW_CHART_MAGNETIC_DISK = 155;
|
||||
public static final int FLOW_CHART_MAGNETIC_DRUM = 156;
|
||||
public static final int FLOW_CHART_DISPLAY = 157;
|
||||
public static final int FLOW_CHART_DELAY = 158;
|
||||
public static final int FLOW_CHART_ALTERNATE_PROCESS = 159;
|
||||
public static final int FLOW_CHART_OFFPAGE_CONNECTOR = 160;
|
||||
public static final int ACTION_BUTTON_BLANK = 161;
|
||||
public static final int ACTION_BUTTON_HOME = 162;
|
||||
public static final int ACTION_BUTTON_HELP = 163;
|
||||
public static final int ACTION_BUTTON_INFORMATION = 164;
|
||||
public static final int ACTION_BUTTON_FORWARD_NEXT = 165;
|
||||
public static final int ACTION_BUTTON_BACK_PREVIOUS = 166;
|
||||
public static final int ACTION_BUTTON_END = 167;
|
||||
public static final int ACTION_BUTTON_BEGINNING = 168;
|
||||
public static final int ACTION_BUTTON_RETURN = 169;
|
||||
public static final int ACTION_BUTTON_DOCUMENT = 170;
|
||||
public static final int ACTION_BUTTON_SOUND = 171;
|
||||
public static final int ACTION_BUTTON_MOVIE = 172;
|
||||
public static final int GEAR_6 = 173;
|
||||
public static final int GEAR_9 = 174;
|
||||
public static final int FUNNEL = 175;
|
||||
public static final int MATH_PLUS = 176;
|
||||
public static final int MATH_MINUS = 177;
|
||||
public static final int MATH_MULTIPLY = 178;
|
||||
public static final int MATH_DIVIDE = 179;
|
||||
public static final int MATH_EQUAL = 180;
|
||||
public static final int MATH_NOT_EQUAL = 181;
|
||||
public static final int CORNER_TABS = 182;
|
||||
public static final int SQUARE_TABS = 183;
|
||||
public static final int PLAQUE_TABS = 184;
|
||||
public static final int CHART_X = 185;
|
||||
public static final int CHART_STAR = 186;
|
||||
public static final int CHART_PLUS = 187;
|
||||
}
|
||||
|
@ -1,69 +1,69 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* This enumeration value indicates the type of vertical alignment for a cell, i.e.,
|
||||
* whether it is aligned top, bottom, vertically centered, justified or distributed.
|
||||
*/
|
||||
public enum VerticalAlignment {
|
||||
/**
|
||||
* The vertical alignment is aligned-to-top.
|
||||
*/
|
||||
TOP,
|
||||
|
||||
/**
|
||||
* The vertical alignment is centered across the height of the cell.
|
||||
*/
|
||||
CENTER,
|
||||
|
||||
/**
|
||||
* The vertical alignment is aligned-to-bottom.
|
||||
*/
|
||||
BOTTOM,
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* When text direction is horizontal: the vertical alignment of lines of text is distributed vertically,
|
||||
* where each line of text inside the cell is evenly distributed across the height of the cell,
|
||||
* with flush top and bottom margins.
|
||||
* </p>
|
||||
* <p>
|
||||
* When text direction is vertical: similar behavior as horizontal justification.
|
||||
* The alignment is justified (flush top and bottom in this case). For each line of text, each
|
||||
* line of the wrapped text in a cell is aligned to the top and bottom (except the last line).
|
||||
* If no single line of text wraps in the cell, then the text is not justified.
|
||||
* </p>
|
||||
*/
|
||||
JUSTIFY,
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* When text direction is horizontal: the vertical alignment of lines of text is distributed vertically,
|
||||
* where each line of text inside the cell is evenly distributed across the height of the cell,
|
||||
* with flush top
|
||||
* </p>
|
||||
* <p>
|
||||
* When text direction is vertical: behaves exactly as distributed horizontal alignment.
|
||||
* The first words in a line of text (appearing at the top of the cell) are flush
|
||||
* with the top edge of the cell, and the last words of a line of text are flush with the bottom edge of the cell,
|
||||
* and the line of text is distributed evenly from top to bottom.
|
||||
* </p>
|
||||
*/
|
||||
DISTRIBUTED
|
||||
}
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
/**
|
||||
* This enumeration value indicates the type of vertical alignment for a cell, i.e.,
|
||||
* whether it is aligned top, bottom, vertically centered, justified or distributed.
|
||||
*/
|
||||
public enum VerticalAlignment {
|
||||
/**
|
||||
* The vertical alignment is aligned-to-top.
|
||||
*/
|
||||
TOP,
|
||||
|
||||
/**
|
||||
* The vertical alignment is centered across the height of the cell.
|
||||
*/
|
||||
CENTER,
|
||||
|
||||
/**
|
||||
* The vertical alignment is aligned-to-bottom.
|
||||
*/
|
||||
BOTTOM,
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* When text direction is horizontal: the vertical alignment of lines of text is distributed vertically,
|
||||
* where each line of text inside the cell is evenly distributed across the height of the cell,
|
||||
* with flush top and bottom margins.
|
||||
* </p>
|
||||
* <p>
|
||||
* When text direction is vertical: similar behavior as horizontal justification.
|
||||
* The alignment is justified (flush top and bottom in this case). For each line of text, each
|
||||
* line of the wrapped text in a cell is aligned to the top and bottom (except the last line).
|
||||
* If no single line of text wraps in the cell, then the text is not justified.
|
||||
* </p>
|
||||
*/
|
||||
JUSTIFY,
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* When text direction is horizontal: the vertical alignment of lines of text is distributed vertically,
|
||||
* where each line of text inside the cell is evenly distributed across the height of the cell,
|
||||
* with flush top
|
||||
* </p>
|
||||
* <p>
|
||||
* When text direction is vertical: behaves exactly as distributed horizontal alignment.
|
||||
* The first words in a line of text (appearing at the top of the cell) are flush
|
||||
* with the top edge of the cell, and the last words of a line of text are flush with the bottom edge of the cell,
|
||||
* and the line of text is distributed evenly from top to bottom.
|
||||
* </p>
|
||||
*/
|
||||
DISTRIBUTED
|
||||
}
|
||||
|
@ -1,34 +1,34 @@
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
/**
|
||||
* Implementors of this interface allow client code to 'delay' writing to a certain section of a
|
||||
* data output stream.<br/>
|
||||
* A typical application is for writing BIFF records when the size is not known until well after
|
||||
* the header has been written. The client code can call {@link #createDelayedOutput(int)}
|
||||
* to reserve two bytes of the output for the 'ushort size' header field. The delayed output can
|
||||
* be written at any stage.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface DelayableLittleEndianOutput extends LittleEndianOutput {
|
||||
/**
|
||||
* Creates an output stream intended for outputting a sequence of <tt>size</tt> bytes.
|
||||
*/
|
||||
LittleEndianOutput createDelayedOutput(int size);
|
||||
}
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
/**
|
||||
* Implementors of this interface allow client code to 'delay' writing to a certain section of a
|
||||
* data output stream.<br/>
|
||||
* A typical application is for writing BIFF records when the size is not known until well after
|
||||
* the header has been written. The client code can call {@link #createDelayedOutput(int)}
|
||||
* to reserve two bytes of the output for the 'ushort size' header field. The delayed output can
|
||||
* be written at any stage.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface DelayableLittleEndianOutput extends LittleEndianOutput {
|
||||
/**
|
||||
* Creates an output stream intended for outputting a sequence of <tt>size</tt> bytes.
|
||||
*/
|
||||
LittleEndianOutput createDelayedOutput(int size);
|
||||
}
|
||||
|
@ -1,34 +1,34 @@
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface LittleEndianInput {
|
||||
int available();
|
||||
byte readByte();
|
||||
int readUByte();
|
||||
short readShort();
|
||||
int readUShort();
|
||||
int readInt();
|
||||
long readLong();
|
||||
double readDouble();
|
||||
void readFully(byte[] buf);
|
||||
void readFully(byte[] buf, int off, int len);
|
||||
}
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface LittleEndianInput {
|
||||
int available();
|
||||
byte readByte();
|
||||
int readUByte();
|
||||
short readShort();
|
||||
int readUShort();
|
||||
int readInt();
|
||||
long readLong();
|
||||
double readDouble();
|
||||
void readFully(byte[] buf);
|
||||
void readFully(byte[] buf, int off, int len);
|
||||
}
|
||||
|
@ -1,144 +1,144 @@
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Wraps an {@link InputStream} providing {@link LittleEndianInput}<p/>
|
||||
*
|
||||
* This class does not buffer any input, so the stream read position maintained
|
||||
* by this class is consistent with that of the inner stream.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class LittleEndianInputStream extends FilterInputStream implements LittleEndianInput {
|
||||
public LittleEndianInputStream(InputStream is) {
|
||||
super(is);
|
||||
}
|
||||
public int available() {
|
||||
try {
|
||||
return super.available();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public byte readByte() {
|
||||
return (byte)readUByte();
|
||||
}
|
||||
public int readUByte() {
|
||||
int ch;
|
||||
try {
|
||||
ch = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(ch);
|
||||
return ch;
|
||||
}
|
||||
public double readDouble() {
|
||||
return Double.longBitsToDouble(readLong());
|
||||
}
|
||||
public int readInt() {
|
||||
int ch1;
|
||||
int ch2;
|
||||
int ch3;
|
||||
int ch4;
|
||||
try {
|
||||
ch1 = in.read();
|
||||
ch2 = in.read();
|
||||
ch3 = in.read();
|
||||
ch4 = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(ch1 | ch2 | ch3 | ch4);
|
||||
return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
|
||||
}
|
||||
public long readLong() {
|
||||
int b0;
|
||||
int b1;
|
||||
int b2;
|
||||
int b3;
|
||||
int b4;
|
||||
int b5;
|
||||
int b6;
|
||||
int b7;
|
||||
try {
|
||||
b0 = in.read();
|
||||
b1 = in.read();
|
||||
b2 = in.read();
|
||||
b3 = in.read();
|
||||
b4 = in.read();
|
||||
b5 = in.read();
|
||||
b6 = in.read();
|
||||
b7 = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7);
|
||||
return (((long)b7 << 56) +
|
||||
((long)b6 << 48) +
|
||||
((long)b5 << 40) +
|
||||
((long)b4 << 32) +
|
||||
((long)b3 << 24) +
|
||||
(b2 << 16) +
|
||||
(b1 << 8) +
|
||||
(b0 << 0));
|
||||
}
|
||||
public short readShort() {
|
||||
return (short)readUShort();
|
||||
}
|
||||
public int readUShort() {
|
||||
int ch1;
|
||||
int ch2;
|
||||
try {
|
||||
ch1 = in.read();
|
||||
ch2 = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(ch1 | ch2);
|
||||
return (ch2 << 8) + (ch1 << 0);
|
||||
}
|
||||
private static void checkEOF(int value) {
|
||||
if (value <0) {
|
||||
throw new RuntimeException("Unexpected end-of-file");
|
||||
}
|
||||
}
|
||||
|
||||
public void readFully(byte[] buf) {
|
||||
readFully(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
public void readFully(byte[] buf, int off, int len) {
|
||||
int max = off+len;
|
||||
for(int i=off; i<max; i++) {
|
||||
int ch;
|
||||
try {
|
||||
ch = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(ch);
|
||||
buf[i] = (byte) ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Wraps an {@link InputStream} providing {@link LittleEndianInput}<p/>
|
||||
*
|
||||
* This class does not buffer any input, so the stream read position maintained
|
||||
* by this class is consistent with that of the inner stream.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class LittleEndianInputStream extends FilterInputStream implements LittleEndianInput {
|
||||
public LittleEndianInputStream(InputStream is) {
|
||||
super(is);
|
||||
}
|
||||
public int available() {
|
||||
try {
|
||||
return super.available();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public byte readByte() {
|
||||
return (byte)readUByte();
|
||||
}
|
||||
public int readUByte() {
|
||||
int ch;
|
||||
try {
|
||||
ch = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(ch);
|
||||
return ch;
|
||||
}
|
||||
public double readDouble() {
|
||||
return Double.longBitsToDouble(readLong());
|
||||
}
|
||||
public int readInt() {
|
||||
int ch1;
|
||||
int ch2;
|
||||
int ch3;
|
||||
int ch4;
|
||||
try {
|
||||
ch1 = in.read();
|
||||
ch2 = in.read();
|
||||
ch3 = in.read();
|
||||
ch4 = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(ch1 | ch2 | ch3 | ch4);
|
||||
return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
|
||||
}
|
||||
public long readLong() {
|
||||
int b0;
|
||||
int b1;
|
||||
int b2;
|
||||
int b3;
|
||||
int b4;
|
||||
int b5;
|
||||
int b6;
|
||||
int b7;
|
||||
try {
|
||||
b0 = in.read();
|
||||
b1 = in.read();
|
||||
b2 = in.read();
|
||||
b3 = in.read();
|
||||
b4 = in.read();
|
||||
b5 = in.read();
|
||||
b6 = in.read();
|
||||
b7 = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7);
|
||||
return (((long)b7 << 56) +
|
||||
((long)b6 << 48) +
|
||||
((long)b5 << 40) +
|
||||
((long)b4 << 32) +
|
||||
((long)b3 << 24) +
|
||||
(b2 << 16) +
|
||||
(b1 << 8) +
|
||||
(b0 << 0));
|
||||
}
|
||||
public short readShort() {
|
||||
return (short)readUShort();
|
||||
}
|
||||
public int readUShort() {
|
||||
int ch1;
|
||||
int ch2;
|
||||
try {
|
||||
ch1 = in.read();
|
||||
ch2 = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(ch1 | ch2);
|
||||
return (ch2 << 8) + (ch1 << 0);
|
||||
}
|
||||
private static void checkEOF(int value) {
|
||||
if (value <0) {
|
||||
throw new RuntimeException("Unexpected end-of-file");
|
||||
}
|
||||
}
|
||||
|
||||
public void readFully(byte[] buf) {
|
||||
readFully(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
public void readFully(byte[] buf, int off, int len) {
|
||||
int max = off+len;
|
||||
for(int i=off; i<max; i++) {
|
||||
int ch;
|
||||
try {
|
||||
ch = in.read();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
checkEOF(ch);
|
||||
buf[i] = (byte) ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface LittleEndianOutput {
|
||||
void writeByte(int v);
|
||||
void writeShort(int v);
|
||||
void writeInt(int v);
|
||||
void writeLong(long v);
|
||||
void writeDouble(double v);
|
||||
void write(byte[] b);
|
||||
void write(byte[] b, int offset, int len);
|
||||
}
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public interface LittleEndianOutput {
|
||||
void writeByte(int v);
|
||||
void writeShort(int v);
|
||||
void writeInt(int v);
|
||||
void writeLong(long v);
|
||||
void writeDouble(double v);
|
||||
void write(byte[] b);
|
||||
void write(byte[] b, int offset, int len);
|
||||
}
|
||||
|
@ -1,91 +1,91 @@
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class LittleEndianOutputStream extends FilterOutputStream implements LittleEndianOutput {
|
||||
public LittleEndianOutputStream(OutputStream out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
public void writeByte(int v) {
|
||||
try {
|
||||
out.write(v);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeDouble(double v) {
|
||||
writeLong(Double.doubleToLongBits(v));
|
||||
}
|
||||
|
||||
public void writeInt(int v) {
|
||||
int b3 = (v >>> 24) & 0xFF;
|
||||
int b2 = (v >>> 16) & 0xFF;
|
||||
int b1 = (v >>> 8) & 0xFF;
|
||||
int b0 = (v >>> 0) & 0xFF;
|
||||
try {
|
||||
out.write(b0);
|
||||
out.write(b1);
|
||||
out.write(b2);
|
||||
out.write(b3);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeLong(long v) {
|
||||
writeInt((int)(v >> 0));
|
||||
writeInt((int)(v >> 32));
|
||||
}
|
||||
|
||||
public void writeShort(int v) {
|
||||
int b1 = (v >>> 8) & 0xFF;
|
||||
int b0 = (v >>> 0) & 0xFF;
|
||||
try {
|
||||
out.write(b0);
|
||||
out.write(b1);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public void write(byte[] b) {
|
||||
// suppress IOException for interface method
|
||||
try {
|
||||
super.write(b);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public void write(byte[] b, int off, int len) {
|
||||
// suppress IOException for interface method
|
||||
try {
|
||||
super.write(b, off, len);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
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.util;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class LittleEndianOutputStream extends FilterOutputStream implements LittleEndianOutput {
|
||||
public LittleEndianOutputStream(OutputStream out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
public void writeByte(int v) {
|
||||
try {
|
||||
out.write(v);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeDouble(double v) {
|
||||
writeLong(Double.doubleToLongBits(v));
|
||||
}
|
||||
|
||||
public void writeInt(int v) {
|
||||
int b3 = (v >>> 24) & 0xFF;
|
||||
int b2 = (v >>> 16) & 0xFF;
|
||||
int b1 = (v >>> 8) & 0xFF;
|
||||
int b0 = (v >>> 0) & 0xFF;
|
||||
try {
|
||||
out.write(b0);
|
||||
out.write(b1);
|
||||
out.write(b2);
|
||||
out.write(b3);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeLong(long v) {
|
||||
writeInt((int)(v >> 0));
|
||||
writeInt((int)(v >> 32));
|
||||
}
|
||||
|
||||
public void writeShort(int v) {
|
||||
int b1 = (v >>> 8) & 0xFF;
|
||||
int b0 = (v >>> 0) & 0xFF;
|
||||
try {
|
||||
out.write(b0);
|
||||
out.write(b1);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public void write(byte[] b) {
|
||||
// suppress IOException for interface method
|
||||
try {
|
||||
super.write(b);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public void write(byte[] b, int off, int len) {
|
||||
// suppress IOException for interface method
|
||||
try {
|
||||
super.write(b, off, len);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user