git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@776377 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_5_BETA6
@@ -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(); | |||
} |
@@ -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); | |||
} | |||
} | |||
} |