summaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/poi/hssf/record/DVALRecord.java157
-rw-r--r--src/java/org/apache/poi/hssf/record/DVRecord.java590
-rw-r--r--src/java/org/apache/poi/hssf/record/RecordFactory.java6
-rw-r--r--src/java/org/apache/poi/hssf/record/StringRecord.java8
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFCell.java2
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java49
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java4
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java88
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFFont.java2
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java93
-rw-r--r--src/java/org/apache/poi/hssf/util/HSSFCellRangeAddress.java253
-rw-r--r--src/java/org/apache/poi/hssf/util/HSSFDataValidation.java471
-rw-r--r--src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java3
-rw-r--r--src/java/org/apache/poi/util/IOUtils.java20
-rw-r--r--src/java/org/apache/poi/util/StringUtil.java3
15 files changed, 1686 insertions, 63 deletions
diff --git a/src/java/org/apache/poi/hssf/record/DVALRecord.java b/src/java/org/apache/poi/hssf/record/DVALRecord.java
new file mode 100644
index 0000000000..858f525ca0
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/record/DVALRecord.java
@@ -0,0 +1,157 @@
+
+/* ====================================================================
+ Copyright 2002-2004 Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record;
+
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * Title: DVAL Record<P>
+ * Description: used in data validation ;
+ * This record is the list header of all data validation records in the current sheet.
+ * @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
+ * @version 2.0-pre
+ */
+
+public class DVALRecord extends Record
+{
+ public final static short sid = 0x01B2;
+
+ //unknown field ; it's size should be 10
+ private short field_unknown = 0x0000;
+
+ //Object ID of the drop down arrow object for list boxes ;
+ //in our case this will be always FFFF , until
+ //MSODrawingGroup and MSODrawing records are implemented
+ private int field_cbo_id = 0xFFFFFFFF;
+
+ //Number of following DV records
+ //Default value is 1
+ private int field_3_dv_no = 0x00000000;
+
+ public DVALRecord()
+ {
+ }
+
+ /**
+ * Constructs a DVAL record and sets its fields appropriately.
+ *
+ * @param in the RecordInputstream to read the record from
+ */
+
+ public DVALRecord(RecordInputStream in)
+ {
+ super(in);
+ }
+
+ protected void validateSid(short id)
+ {
+ if (id != sid)
+ {
+ throw new RecordFormatException("NOT A valid DVAL RECORD");
+ }
+ }
+
+ protected void fillFields(RecordInputStream in)
+ {
+ for ( int i=0; i<5; i++)
+ {
+ this.field_unknown = in.readShort();
+ }
+ this.field_cbo_id = in.readInt();
+ this.field_3_dv_no = in.readInt();
+ }
+
+ /**
+ * set the object ID of the drop down arrow object for list boxes
+ * @param cboID - Object ID
+ */
+ public void setObjectID(int cboID)
+ {
+ this.field_cbo_id = cboID;
+ }
+
+ /**
+ * Set the number of following DV records
+ * @param dvNo - the DV records number
+ */
+ public void setDVRecNo(int dvNo)
+ {
+ this.field_3_dv_no = dvNo;
+ }
+
+ /**
+ * get Object ID of the drop down arrow object for list boxes
+ */
+ public int getObjectID( )
+ {
+ return this.field_cbo_id;
+ }
+
+ /**
+ * Get number of following DV records
+ */
+ public int getDVRecNo( )
+ {
+ return this.field_3_dv_no;
+ }
+
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("[DVAL]\n");
+ buffer.append(" .comboObjectID = ").append(Integer.toHexString(this.getObjectID())).append("\n");
+ buffer.append(" .DVRecordsNumber = ").append(Integer.toHexString(this.getDVRecNo())).append("\n");
+ buffer.append("[/DVAL]\n");
+ return buffer.toString();
+ }
+
+ public int serialize(int offset, byte [] data)
+ {
+ LittleEndian.putShort(data, 0 + offset, this.sid);
+ LittleEndian.putShort(data, 2 + offset, ( short)(this.getRecordSize()-4));
+ for ( int i=0; i<5; i++)
+ {
+ LittleEndian.putShort(data, 4 + i*2 + offset, (short)this.field_unknown);
+ }
+ LittleEndian.putInt(data, 14 + offset, this.getObjectID());
+ LittleEndian.putInt(data, 18 + offset, this.getDVRecNo());
+ return getRecordSize();
+ }
+
+ //with 4 bytes header
+ public int getRecordSize()
+ {
+ return 22;
+ }
+
+ public short getSid()
+ {
+ return this.sid;
+ }
+
+ public Object clone()
+ {
+ DVALRecord rec = new DVALRecord();
+ rec.field_unknown = this.field_unknown;
+ rec.field_cbo_id = this.field_cbo_id;
+ rec.field_3_dv_no = this.field_3_dv_no;
+ return rec;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/poi/hssf/record/DVRecord.java b/src/java/org/apache/poi/hssf/record/DVRecord.java
new file mode 100644
index 0000000000..0bae009bd3
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/record/DVRecord.java
@@ -0,0 +1,590 @@
+/* ====================================================================
+ Copyright 2002-2004 Apache Software Foundation
+
+ Licensed 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.BitField;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.StringUtil;
+import org.apache.poi.hssf.util.HSSFCellRangeAddress;
+import org.apache.poi.hssf.record.formula.Ptg;
+
+import java.io.IOException;
+import java.util.Stack;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/**
+ * Title: DV Record<P>
+ * Description: This record stores data validation settings and a list of cell ranges
+ * which contain these settings. The data validation settings of a sheet
+ * are stored in a sequential list of DV records. This list is followed by
+ * DVAL record(s)
+ * @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
+ * @version 2.0-pre
+ */
+public class DVRecord extends Record
+{
+ public final static short sid = 0x01BE;
+
+ /**
+ * Option flags
+ */
+ private int field_option_flags;
+
+ /**
+ * Title of the prompt box
+ */
+ private String field_title_prompt;
+
+ /**
+ * Title of the error box
+ */
+ private String field_title_error;
+
+ /**
+ * Text of the prompt box
+ */
+ private String field_text_prompt;
+
+ /**
+ * Text of the error box
+ */
+ private String field_text_error;
+
+ /**
+ * Size of the formula data for first condition
+ */
+ private short field_size_first_formula;
+
+ /**
+ * Not used
+ */
+ private short field_not_used_1 = 0x3FE0;
+
+ /**
+ * Formula data for first condition (RPN token array without size field)
+ */
+ private Stack field_rpn_token_1 ;
+
+ /**
+ * Size of the formula data for second condition
+ */
+ private short field_size_sec_formula;
+
+ /**
+ * Not used
+ */
+ private short field_not_used_2 = 0x0000;
+
+ /**
+ * Formula data for second condition (RPN token array without size field)
+ */
+ private Stack field_rpn_token_2 ;
+
+ /**
+ * Cell range address list with all affected ranges
+ */
+ private HSSFCellRangeAddress field_regions;
+
+ public static final Integer STRING_PROMPT_TITLE = new Integer(0);
+ public static final Integer STRING_ERROR_TITLE = new Integer(1);
+ public static final Integer STRING_PROMPT_TEXT = new Integer(2);
+ public static final Integer STRING_ERROR_TEXT = new Integer(3);
+ private Hashtable _hash_strings ;
+
+ /**
+ * Option flags field
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ private BitField opt_data_type = new BitField(0x0000000F);
+ private BitField opt_error_style = new BitField(0x00000070);
+ private BitField opt_string_list_formula = new BitField(0x00000080);
+ private BitField opt_empty_cell_allowed = new BitField(0x00000100);
+ private BitField opt_surppres_dropdown_arrow = new BitField(0x00000200);
+ private BitField opt_show_prompt_on_cell_selected = new BitField(0x00040000);
+ private BitField opt_show_error_on_invalid_value = new BitField(0x00080000);
+ private BitField opt_condition_operator = new BitField(0x00F00000);
+
+ public DVRecord()
+ {
+ }
+
+ /**
+ * Constructs a DV record and sets its fields appropriately.
+ *
+ * @param in the RecordInputstream to read the record from
+ */
+
+ public DVRecord(RecordInputStream in)
+ {
+ super(in);
+ }
+
+ protected void validateSid(short id)
+ {
+ if (id != sid)
+ {
+ throw new RecordFormatException("NOT a valid DV RECORD");
+ }
+ }
+
+ protected void fillFields(RecordInputStream in)
+ {
+ field_rpn_token_1 = new Stack();
+ field_rpn_token_2 = new Stack();
+
+ this.field_option_flags = in.readInt();
+ this._hash_strings = new Hashtable(4);
+
+ StringHandler strHandler_prompt_title = new StringHandler( in );
+ this.field_title_prompt = strHandler_prompt_title.getStringData();
+ this._hash_strings.put(DVRecord.STRING_PROMPT_TITLE, strHandler_prompt_title);
+
+ StringHandler strHandler_error_title = new StringHandler( in );
+ this.field_title_error = strHandler_error_title.getStringData();
+ this._hash_strings.put(DVRecord.STRING_ERROR_TITLE, strHandler_error_title);
+
+ StringHandler strHandler_prompt_text = new StringHandler( in );
+ this.field_text_prompt = strHandler_prompt_text.getStringData();
+ this._hash_strings.put(DVRecord.STRING_PROMPT_TEXT, strHandler_prompt_text);
+
+ StringHandler strHandler_error_text = new StringHandler( in );
+ this.field_text_error = strHandler_error_text.getStringData();
+ this._hash_strings.put(DVRecord.STRING_ERROR_TEXT, strHandler_error_text);
+
+ this.field_size_first_formula = in.readShort();
+ this.field_not_used_1 = in.readShort();
+
+ //read first formula data condition
+ // Not sure if this was needed or not...
+// try {
+// in.skip(this.field_size_first_formula);
+// } catch(IOException e) { throw new IllegalStateException(e); }
+
+ int token_pos = 0;
+ while (token_pos < this.field_size_first_formula)
+ {
+ Ptg ptg = Ptg.createPtg(in);
+ token_pos += ptg.getSize();
+ field_rpn_token_1.push(ptg);
+ }
+
+ this.field_size_sec_formula = in.readShort();
+ this.field_not_used_2 = in.readShort();
+
+ //read sec formula data condition
+ // Not sure if this was needed or not...
+ try {
+ in.skip(this.field_size_sec_formula);
+ } catch(IOException e) { throw new IllegalStateException(e); }
+
+ token_pos = 0;
+ while (token_pos < this.field_size_sec_formula)
+ {
+ Ptg ptg = Ptg.createPtg(in);
+ token_pos += ptg.getSize();
+ field_rpn_token_2.push(ptg);
+ }
+
+ //read cell range address list with all affected ranges
+ this.field_regions = new HSSFCellRangeAddress(in);
+ }
+
+
+ // --> start option flags
+ /**
+ * set the condition data type
+ * @param type - condition data type
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public void setDataType(int type)
+ {
+ this.field_option_flags = this.opt_data_type.setValue(this.field_option_flags, type);
+ }
+
+ /**
+ * get the condition data type
+ * @return the condition data type
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public int getDataType()
+ {
+ return this.opt_data_type.getValue(this.field_option_flags);
+ }
+
+ /**
+ * set the condition error style
+ * @param type - condition error style
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public void setErrorStyle(int style)
+ {
+ this.field_option_flags = this.opt_error_style.setValue(this.field_option_flags, style);
+ }
+
+ /**
+ * get the condition error style
+ * @return the condition error style
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public int getErrorStyle()
+ {
+ return this.opt_error_style.getValue(this.field_option_flags);
+ }
+
+ /**
+ * set if in list validations the string list is explicitly given in the formula
+ * @param type - true if in list validations the string list is explicitly given in the formula; false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public void setListExplicitFormula(boolean explicit)
+ {
+ this.field_option_flags = this.opt_string_list_formula.setBoolean(this.field_option_flags, explicit);
+ }
+
+ /**
+ * return true if in list validations the string list is explicitly given in the formula, false otherwise
+ * @return true if in list validations the string list is explicitly given in the formula, false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public boolean getListExplicitFormula()
+ {
+ return (this.opt_string_list_formula.isSet(this.field_option_flags));
+ }
+
+ /**
+ * set if empty values are allowed in cells
+ * @param type - true if empty values are allowed in cells, false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public void setEmptyCellAllowed(boolean allowed)
+ {
+ this.field_option_flags = this.opt_empty_cell_allowed.setBoolean(this.field_option_flags, allowed);
+ }
+
+ /**
+ * return true if empty values are allowed in cells, false otherwise
+ * @return if empty values are allowed in cells, false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public boolean getEmptyCellAllowed()
+ {
+ return (this.opt_empty_cell_allowed.isSet(this.field_option_flags));
+ }
+
+ /**
+ * set if drop down arrow should be surppressed when list validation is used
+ * @param type - true if drop down arrow should be surppressed when list validation is used, false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public void setSurppresDropdownArrow(boolean surppress)
+ {
+ this.field_option_flags = this.opt_surppres_dropdown_arrow.setBoolean(this.field_option_flags, surppress);
+ }
+
+ /**
+ * return true if drop down arrow should be surppressed when list validation is used, false otherwise
+ * @return if drop down arrow should be surppressed when list validation is used, false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public boolean getSurppresDropdownArrow()
+ {
+ return (this.opt_surppres_dropdown_arrow.isSet(this.field_option_flags));
+ }
+
+ /**
+ * set if a prompt window should appear when cell is selected
+ * @param type - true if a prompt window should appear when cell is selected, false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public void setShowPromptOnCellSelected(boolean show)
+ {
+ this.field_option_flags = this.opt_show_prompt_on_cell_selected.setBoolean(this.field_option_flags, show);
+ }
+
+ /**
+ * return true if a prompt window should appear when cell is selected, false otherwise
+ * @return if a prompt window should appear when cell is selected, false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public boolean getShowPromptOnCellSelected()
+ {
+ return (this.opt_show_prompt_on_cell_selected.isSet(this.field_option_flags));
+ }
+
+ /**
+ * set if an error window should appear when an invalid value is entered in the cell
+ * @param type - true if an error window should appear when an invalid value is entered in the cell, false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public void setShowErrorOnInvalidValue(boolean show)
+ {
+ this.field_option_flags = this.opt_show_error_on_invalid_value.setBoolean(this.field_option_flags, show);
+ }
+
+ /**
+ * return true if an error window should appear when an invalid value is entered in the cell, false otherwise
+ * @return if an error window should appear when an invalid value is entered in the cell, false otherwise
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public boolean getShowErrorOnInvalidValue()
+ {
+ return (this.opt_show_error_on_invalid_value.isSet(this.field_option_flags));
+ }
+
+ /**
+ * set the condition operator
+ * @param type - condition operator
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public void setConditionOperator(int operator)
+ {
+ this.field_option_flags = this.opt_condition_operator.setValue(this.field_option_flags, operator);
+ }
+
+ /**
+ * get the condition operator
+ * @return the condition operator
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public int getConditionOperator()
+ {
+ return this.opt_condition_operator.getValue(this.field_option_flags);
+ }
+ // <-- end option flags
+
+ public void setFirstFormulaRPN( Stack rpn )
+ {
+ this.field_rpn_token_1 = rpn;
+ }
+
+ public void setFirstFormulaSize( short size )
+ {
+ this.field_size_first_formula = size;
+ }
+
+ public void setSecFormulaRPN( Stack rpn )
+ {
+ this.field_rpn_token_2 = rpn;
+ }
+
+ public void setSecFormulaSize( short size )
+ {
+ this.field_size_sec_formula = size;
+ }
+
+ public void setStringField( Integer type, String str_data )
+ {
+ if ( this._hash_strings == null )
+ {
+ this._hash_strings = new Hashtable();
+ }
+ StringHandler strHandler = new StringHandler();
+ if ( str_data == null )
+ {
+ str_data = "";
+ }
+ else
+ {
+ strHandler.setStringLength(str_data.length());
+ }
+ strHandler.setStringData(str_data);
+
+ strHandler.setUnicodeFlag((byte)0x00);
+ this._hash_strings.put( type, strHandler);
+ }
+
+ public String getStringField( Integer type )
+ {
+ return ((StringHandler)this._hash_strings.get(type)).getStringData();
+ }
+
+ public void setCellRangeAddress( HSSFCellRangeAddress range )
+ {
+ this.field_regions = range;
+ }
+
+ public HSSFCellRangeAddress getCellRangeAddress( )
+ {
+ return this.field_regions;
+ }
+
+ /**
+ * gets the option flags field.
+ * @return options - the option flags field
+ */
+ public int getOptionFlags()
+ {
+ return this.field_option_flags;
+ }
+
+ public String toString()
+ {
+ /** @todo DVRecord string representation */
+ StringBuffer buffer = new StringBuffer();
+
+ return buffer.toString();
+ }
+
+ public int serialize(int offset, byte [] data)
+ {
+ int size = this.getRecordSize();
+ LittleEndian.putShort(data, 0 + offset, sid);
+ LittleEndian.putShort(data, 2 + offset, ( short ) (size-4));
+
+ int pos = 4;
+ LittleEndian.putInt(data, pos + offset, this.getOptionFlags());
+ pos += 4;
+ pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_PROMPT_TITLE )).serialize(pos+offset, data);
+ pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_ERROR_TITLE )).serialize(pos+offset, data);
+ pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_PROMPT_TEXT )).serialize(pos+offset, data);
+ pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_ERROR_TEXT )).serialize(pos+offset, data);
+ LittleEndian.putShort(data, offset+pos, this.field_size_first_formula);
+ pos += 2;
+ LittleEndian.putShort(data, offset+pos, this.field_not_used_1);
+ pos += 2;
+
+ for (int k = 0; k < this.field_rpn_token_1.size(); k++)
+ {
+ Ptg ptg = ( Ptg ) this.field_rpn_token_1.get(k);
+ ptg.writeBytes(data, pos+offset);
+ pos += ptg.getSize();
+ }
+
+ LittleEndian.putShort(data, offset+pos, this.field_size_sec_formula);
+ pos += 2;
+ LittleEndian.putShort(data, offset+pos, this.field_not_used_2);
+ pos += 2;
+ if ( this.field_size_sec_formula > 0 )
+ {
+ for (int k = 0; k < this.field_rpn_token_2.size(); k++)
+ {
+ Ptg ptg = ( Ptg ) this.field_rpn_token_2.get(k);
+ ptg.writeBytes(data, pos+offset);
+ pos += ptg.getSize();
+ }
+ }
+ this.field_regions.serialize(pos+offset, data);
+ return size;
+ }
+
+ public int getRecordSize()
+ {
+ int size = 4+4+2+2+2+2;//header+options_field+first_formula_size+first_unused+sec_formula_size+sec+unused;
+ if ( this._hash_strings != null )
+ {
+ Enumeration enum_keys = this._hash_strings.keys();
+ while ( enum_keys.hasMoreElements() )
+ {
+ size += ((StringHandler)this._hash_strings.get( (Integer)enum_keys.nextElement() )).getSize();
+ }
+ }
+ size += this.field_size_first_formula+ this.field_size_sec_formula;
+ size += this.field_regions.getSize();
+ return size;
+ }
+
+ public short getSid()
+ {
+ return this.sid;
+ }
+
+ /**@todo DVRecord = Serializare */
+
+ private class StringHandler
+ {
+ private int _string_length = 0x0001;
+ private byte _string_unicode_flag = 0x00;
+ private String _string_data = "0x00";
+ private int _start_offset;
+ private int _end_offset;
+
+ StringHandler()
+ {
+
+ }
+
+ StringHandler(RecordInputStream in)
+ {
+ this.fillFields(in);
+ }
+
+ protected void fillFields(RecordInputStream in)
+ {
+ this._string_length = in.readUShort();
+ this._string_unicode_flag = in.readByte();
+ if (this._string_unicode_flag == 1)
+ {
+ this._string_data = in.readUnicodeLEString(this._string_length);
+ }
+ else
+ {
+ this._string_data = in.readCompressedUnicode(this._string_length);
+ }
+ }
+
+ private void setStringData( String string_data )
+ {
+ this._string_data = string_data;
+ }
+
+ private String getStringData()
+ {
+ return this._string_data;
+ }
+
+ private int getEndOffset()
+ {
+ return this._end_offset;
+ }
+
+ public int serialize( int offset, byte[] data )
+ {
+ LittleEndian.putUShort(data, offset, this._string_length );
+ data[2 + offset] = this._string_unicode_flag;
+ if (this._string_unicode_flag == 1)
+ {
+ StringUtil.putUnicodeLE(this._string_data, data, 3 + offset);
+ }
+ else
+ {
+ StringUtil.putCompressedUnicode(this._string_data, data, 3 + offset);
+ }
+ return getSize();
+ }
+
+ private void setUnicodeFlag( byte flag )
+ {
+ this._string_unicode_flag = flag;
+ }
+
+ private void setStringLength( int len )
+ {
+ this._string_length = len;
+ }
+
+ private int getStringByteLength()
+ {
+ return (this._string_unicode_flag == 1) ? this._string_length * 2 : this._string_length;
+ }
+
+ public int getSize()
+ {
+ return 2 + 1 + getStringByteLength();
+ }
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/record/RecordFactory.java b/src/java/org/apache/poi/hssf/record/RecordFactory.java
index 927d5f08be..cf705a316d 100644
--- a/src/java/org/apache/poi/hssf/record/RecordFactory.java
+++ b/src/java/org/apache/poi/hssf/record/RecordFactory.java
@@ -75,7 +75,8 @@ public class RecordFactory
HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class,
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
NoteRecord.class, ObjectProtectRecord.class, ScenarioProtectRecord.class,
- FileSharingRecord.class, ChartTitleFormatRecord.class
+ FileSharingRecord.class, ChartTitleFormatRecord.class,
+ DVRecord.class, DVALRecord.class
};
}
private static Map recordsMap = recordsToMap(records);
@@ -146,6 +147,9 @@ public class RecordFactory
} else if (record.getSid() == ContinueRecord.sid &&
(lastRecord instanceof DrawingGroupRecord)) {
((DrawingGroupRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
+ } else if (record.getSid() == ContinueRecord.sid &&
+ (lastRecord instanceof StringRecord)) {
+ ((StringRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
} else if (record.getSid() == ContinueRecord.sid) {
if (lastRecord instanceof UnknownRecord) {
//Gracefully handle records that we dont know about,
diff --git a/src/java/org/apache/poi/hssf/record/StringRecord.java b/src/java/org/apache/poi/hssf/record/StringRecord.java
index a880d7235b..b3a42aaba4 100644
--- a/src/java/org/apache/poi/hssf/record/StringRecord.java
+++ b/src/java/org/apache/poi/hssf/record/StringRecord.java
@@ -83,6 +83,14 @@ public class StringRecord
field_3_string = StringUtil.getFromCompressedUnicode(data, 0, field_1_string_length);
}
}
+
+ public void processContinueRecord(byte[] data) {
+ if(isUnCompressedUnicode()) {
+ field_3_string += StringUtil.getFromUnicodeLE(data, 0, field_1_string_length - field_3_string.length());
+ } else {
+ field_3_string += StringUtil.getFromCompressedUnicode(data, 0, field_1_string_length - field_3_string.length());
+ }
+ }
public boolean isInValueSection()
{
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
index ac3943da46..9cc4550719 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
@@ -521,7 +521,7 @@ public class HSSFCell
*/
public void setCellValue(Date value)
{
- setCellValue(HSSFDateUtil.getExcelDate(value));
+ setCellValue(HSSFDateUtil.getExcelDate(value, this.book.isUsing1904DateWindowing()));
}
/**
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
index e2725937fa..cdea9ee5be 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
@@ -294,10 +294,24 @@ public class HSSFCellStyle
format.setFontIndex(fontindex);
}
+ /**
+ * gets the index of the font for this style
+ * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getFontAt(short)
+ */
public short getFontIndex()
{
return format.getFontIndex();
}
+
+ /**
+ * gets the font for this style
+ * @param parentWorkbook The HSSFWorkbook that this style belongs to
+ * @see org.apache.poi.hssf.usermodel.HSSFCellStyle#getFontIndex()
+ * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getFontAt(short)
+ */
+ public HSSFFont getFont(HSSFWorkbook parentWorkbook) {
+ return parentWorkbook.getFontAt(getFontIndex());
+ }
/**
* set the cell's using this style to be hidden
@@ -689,7 +703,6 @@ public class HSSFCellStyle
* @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT
*/
-
public short getBorderBottom()
{
return format.getBorderBottom();
@@ -697,9 +710,8 @@ public class HSSFCellStyle
/**
* set the color to use for the left border
- * @param color
+ * @param color The index of the color definition
*/
-
public void setLeftBorderColor(short color)
{
format.setLeftBorderPaletteIdx(color);
@@ -707,9 +719,9 @@ public class HSSFCellStyle
/**
* get the color to use for the left border
- * @return color
+ * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
+ * @param color The index of the color definition
*/
-
public short getLeftBorderColor()
{
return format.getLeftBorderPaletteIdx();
@@ -717,9 +729,8 @@ public class HSSFCellStyle
/**
* set the color to use for the right border
- * @param color
+ * @param color The index of the color definition
*/
-
public void setRightBorderColor(short color)
{
format.setRightBorderPaletteIdx(color);
@@ -727,9 +738,9 @@ public class HSSFCellStyle
/**
* get the color to use for the left border
- * @return color
+ * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
+ * @param color The index of the color definition
*/
-
public short getRightBorderColor()
{
return format.getRightBorderPaletteIdx();
@@ -737,9 +748,8 @@ public class HSSFCellStyle
/**
* set the color to use for the top border
- * @param color
+ * @param color The index of the color definition
*/
-
public void setTopBorderColor(short color)
{
format.setTopBorderPaletteIdx(color);
@@ -747,9 +757,9 @@ public class HSSFCellStyle
/**
* get the color to use for the top border
- * @return color
+ * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
+ * @param color The index of the color definition
*/
-
public short getTopBorderColor()
{
return format.getTopBorderPaletteIdx();
@@ -757,9 +767,8 @@ public class HSSFCellStyle
/**
* set the color to use for the bottom border
- * @param color
+ * @param color The index of the color definition
*/
-
public void setBottomBorderColor(short color)
{
format.setBottomBorderPaletteIdx(color);
@@ -767,9 +776,9 @@ public class HSSFCellStyle
/**
* get the color to use for the left border
- * @return color
+ * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
+ * @param color The index of the color definition
*/
-
public short getBottomBorderColor()
{
return format.getBottomBorderPaletteIdx();
@@ -871,9 +880,9 @@ public class HSSFCellStyle
/**
* get the background fill color
+ * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @return fill color
*/
-
public short getFillBackgroundColor()
{
short result = format.getFillBackground();
@@ -889,7 +898,6 @@ public class HSSFCellStyle
* <i>Note: Ensure Foreground color is set prior to background color.</i>
* @param bg color
*/
-
public void setFillForegroundColor(short bg)
{
format.setFillForeground(bg);
@@ -898,12 +906,11 @@ public class HSSFCellStyle
/**
* get the foreground fill color
+ * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @return fill color
*/
-
public short getFillForegroundColor()
{
return format.getFillForeground();
}
-
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java
index 04a0f57328..4d9098d75a 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java
@@ -82,8 +82,8 @@ public class HSSFClientAnchor
*/
public float getAnchorHeightInPoints(HSSFSheet sheet )
{
- int y1 = Math.min( getDy1(), getDy2() );
- int y2 = Math.max( getDy1(), getDy2() );
+ int y1 = getDy1();
+ int y2 = getDy2();
int row1 = Math.min( getRow1(), getRow2() );
int row2 = Math.max( getRow1(), getRow2() );
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java
index fc9ac3a3b3..fb3a92df86 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java
@@ -35,6 +35,8 @@ import java.util.GregorianCalendar;
* @author Glen Stampoultzis (glens at apache.org)
* @author Dan Sherman (dsherman at isisph.com)
* @author Hack Kampbjorn (hak at 2mba.dk)
+ * @author Alex Jacoby (ajacoby at gmail.com)
+ * @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
*/
public class HSSFDateUtil
@@ -54,19 +56,26 @@ public class HSSFDateUtil
* @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1)
* @param date the Date
*/
-
- public static double getExcelDate(Date date)
- {
+ public static double getExcelDate(Date date) {
+ return getExcelDate(date, false);
+ }
+ /**
+ * Given a Date, converts it into a double representing its internal Excel representation,
+ * which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds.
+ *
+ * @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1)
+ * @param date the Date
+ * @param use1904windowing Should 1900 or 1904 date windowing be used?
+ */
+ public static double getExcelDate(Date date, boolean use1904windowing) {
Calendar calStart = new GregorianCalendar();
-
- calStart.setTime(
- date); // If date includes hours, minutes, and seconds, set them to 0
- if (calStart.get(Calendar.YEAR) < 1900)
+ calStart.setTime(date); // If date includes hours, minutes, and seconds, set them to 0
+
+ if ((!use1904windowing && calStart.get(Calendar.YEAR) < 1900) ||
+ (use1904windowing && calStart.get(Calendar.YEAR) < 1904))
{
return BAD_DATE;
- }
- else
- {
+ } else {
// Because of daylight time saving we cannot use
// date.getTime() - calStart.getTimeInMillis()
// as the difference in milliseconds between 00:00 and 04:00
@@ -80,32 +89,39 @@ public class HSSFDateUtil
) * 1000 + calStart.get(Calendar.MILLISECOND)
) / ( double ) DAY_MILLISECONDS;
calStart = dayStart(calStart);
-
- double value = fraction + absoluteDay(calStart);
- if (value >= 60) {
- value += 1;
+ double value = fraction + absoluteDay(calStart, use1904windowing);
+
+ if (!use1904windowing && value >= 60) {
+ value++;
+ } else if (use1904windowing) {
+ value--;
}
return value;
}
}
-
+
/**
- * Given a excel date, converts it into a Date.
- * Assumes 1900 date windowing.
+ * Given an Excel date with using 1900 date windowing, and
+ * converts it to a java.util.Date.
*
- * @param date the Excel Date
- *
- * @return Java representation of a date (null if error)
- * @see #getJavaDate(double,boolean)
+ * NOTE: If the default <code>TimeZone</code> in Java uses Daylight
+ * Saving Time then the conversion back to an Excel date may not give
+ * the same value, that is the comparison
+ * <CODE>excelDate == getExcelDate(getJavaDate(excelDate,false))</CODE>
+ * is not always true. For example if default timezone is
+ * <code>Europe/Copenhagen</code>, on 2004-03-28 the minute after
+ * 01:59 CET is 03:00 CEST, if the excel date represents a time between
+ * 02:00 and 03:00 then it is converted to past 03:00 summer time
+ *
+ * @param date The Excel date.
+ * @return Java representation of the date, or null if date is not a valid Excel date
+ * @see java.util.TimeZone
*/
-
- public static Date getJavaDate(double date)
- {
- return getJavaDate(date,false);
+ public static Date getJavaDate(double date) {
+ return getJavaDate(date, false);
}
-
/**
* Given an Excel date with either 1900 or 1904 date windowing,
* converts it to a java.util.Date.
@@ -142,7 +158,7 @@ public class HSSFDateUtil
GregorianCalendar calendar = new GregorianCalendar(startYear,0,
wholeDays + dayAdjust);
int millisecondsInDay = (int)((date - Math.floor(date)) *
- (double) DAY_MILLISECONDS + 0.5);
+ DAY_MILLISECONDS + 0.5);
calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
return calendar.getTime();
}
@@ -238,7 +254,7 @@ public class HSSFDateUtil
* Check if a cell contains a date
* Since dates are stored internally in Excel as double values
* we infer it is a date if it is formatted as such.
- * @see #isADateFormat(int,string)
+ * @see #isADateFormat(int, String)
* @see #isInternalDateFormat(int)
*/
public static boolean isCellDateFormatted(HSSFCell cell) {
@@ -259,7 +275,7 @@ public class HSSFDateUtil
* excel date formats.
* As Excel stores a great many of its dates in "non-internal"
* date formats, you will not normally want to use this method.
- * @see #isADateFormat(int,string)
+ * @see #isADateFormat(int,String)
* @see #isInternalDateFormat(int)
*/
public static boolean isCellInternalDateFormatted(HSSFCell cell) {
@@ -296,10 +312,10 @@ public class HSSFDateUtil
* @exception IllegalArgumentException if date is invalid
*/
- private static int absoluteDay(Calendar cal)
+ static int absoluteDay(Calendar cal, boolean use1904windowing)
{
return cal.get(Calendar.DAY_OF_YEAR)
- + daysInPriorYears(cal.get(Calendar.YEAR));
+ + daysInPriorYears(cal.get(Calendar.YEAR), use1904windowing);
}
/**
@@ -307,14 +323,14 @@ public class HSSFDateUtil
*
* @return days number of days in years prior to yr.
* @param yr a year (1900 < yr < 4000)
+ * @param use1904windowing
* @exception IllegalArgumentException if year is outside of range.
*/
- private static int daysInPriorYears(int yr)
+ private static int daysInPriorYears(int yr, boolean use1904windowing)
{
- if (yr < 1900) {
- throw new IllegalArgumentException(
- "'year' must be 1900 or greater");
+ if ((!use1904windowing && yr < 1900) || (use1904windowing && yr < 1900)) {
+ throw new IllegalArgumentException("'year' must be 1900 or greater");
}
int yr1 = yr - 1;
@@ -323,7 +339,7 @@ public class HSSFDateUtil
+ yr1 / 400 // plus years divisible by 400
- 460; // leap days in previous 1900 years
- return 365 * (yr - 1900) + leapDays;
+ return 365 * (yr - (use1904windowing ? 1904 : 1900)) + leapDays;
}
// set HH:MM:SS fields of cal to 00:00:00:000
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFont.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFont.java
index 852e15ee28..cfaa5e4f48 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFFont.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFont.java
@@ -281,8 +281,8 @@ public class HSSFFont
* @return color to use
* @see #COLOR_NORMAL
* @see #COLOR_RED
+ * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
*/
-
public short getColor()
{
return font.getColorPaletteIndex();
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
index 91098c2dcb..b52fa1e5b2 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
@@ -23,9 +23,13 @@
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.*;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.util.HSSFCellRangeAddress;
+import org.apache.poi.hssf.util.HSSFDataValidation;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.util.POILogFactory;
@@ -35,6 +39,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Stack;
import java.util.TreeMap;
import java.text.AttributedString;
import java.text.NumberFormat;
@@ -353,6 +358,94 @@ public class HSSFSheet
{
return lastrow;
}
+
+ /**
+ * Creates a data validation object
+ * @param obj_validation The Data validation object settings
+ */
+ public void addValidationData(HSSFDataValidation obj_validation)
+ {
+ if ( obj_validation == null )
+ {
+ return;
+ }
+ DVALRecord dvalRec = (DVALRecord)sheet.findFirstRecordBySid( DVALRecord.sid );
+ int eofLoc = sheet.findFirstRecordLocBySid( EOFRecord.sid );
+ if ( dvalRec == null )
+ {
+ dvalRec = new DVALRecord();
+ sheet.getRecords().add( eofLoc, dvalRec );
+ }
+ int curr_dvRecNo = dvalRec.getDVRecNo();
+ dvalRec.setDVRecNo(curr_dvRecNo+1);
+
+ //create dv record
+ DVRecord dvRecord = new DVRecord();
+
+ //dv record's option flags
+ dvRecord.setDataType( obj_validation.getDataValidationType() );
+ dvRecord.setErrorStyle(obj_validation.getErrorStyle());
+ dvRecord.setEmptyCellAllowed(obj_validation.getEmptyCellAllowed());
+ dvRecord.setSurppresDropdownArrow(obj_validation.getSurppressDropDownArrow());
+ dvRecord.setShowPromptOnCellSelected(obj_validation.getShowPromptBox());
+ dvRecord.setShowErrorOnInvalidValue(obj_validation.getShowErrorBox());
+ dvRecord.setConditionOperator(obj_validation.getOperator());
+
+ //string fields
+ dvRecord.setStringField( DVRecord.STRING_PROMPT_TITLE,obj_validation.getPromptBoxTitle());
+ dvRecord.setStringField( DVRecord.STRING_PROMPT_TEXT, obj_validation.getPromptBoxText());
+ dvRecord.setStringField( DVRecord.STRING_ERROR_TITLE, obj_validation.getErrorBoxTitle());
+ dvRecord.setStringField( DVRecord.STRING_ERROR_TEXT, obj_validation.getErrorBoxText());
+
+ //formula fields ( size and data )
+ String str_formula = obj_validation.getFirstFormula();
+ FormulaParser fp = new FormulaParser(str_formula+";",book);
+ fp.parse();
+ Stack ptg_arr = new Stack();
+ Ptg[] ptg = fp.getRPNPtg();
+ int size = 0;
+ for (int k = 0; k < ptg.length; k++)
+ {
+ if ( ptg[k] instanceof org.apache.poi.hssf.record.formula.AreaPtg )
+ {
+ //we should set ptgClass to Ptg.CLASS_REF and explicit formula string to false
+ ptg[k].setClass(Ptg.CLASS_REF);
+ obj_validation.setExplicitListFormula(false);
+ }
+ size += ptg[k].getSize();
+ ptg_arr.push(ptg[k]);
+ }
+ dvRecord.setFirstFormulaRPN(ptg_arr);
+ dvRecord.setFirstFormulaSize((short)size);
+
+ dvRecord.setListExplicitFormula(obj_validation.getExplicitListFormula());
+
+ if ( obj_validation.getSecondFormula() != null )
+ {
+ str_formula = obj_validation.getSecondFormula();
+ fp = new FormulaParser(str_formula+";",book);
+ fp.parse();
+ ptg_arr = new Stack();
+ ptg = fp.getRPNPtg();
+ size = 0;
+ for (int k = 0; k < ptg.length; k++)
+ {
+ size += ptg[k].getSize();
+ ptg_arr.push(ptg[k]);
+ }
+ dvRecord.setSecFormulaRPN(ptg_arr);
+ dvRecord.setSecFormulaSize((short)size);
+ }
+
+ //dv records cell range field
+ HSSFCellRangeAddress cell_range = new HSSFCellRangeAddress();
+ cell_range.addADDRStructure(obj_validation.getFirstRow(), obj_validation.getFirstColumn(), obj_validation.getLastRow(), obj_validation.getLastColumn());
+ dvRecord.setCellRangeAddress(cell_range);
+
+ //add dv record
+ eofLoc = sheet.findFirstRecordLocBySid( EOFRecord.sid );
+ sheet.getRecords().add( eofLoc, dvRecord );
+ }
/**
* Get the visibility state for a given column.
diff --git a/src/java/org/apache/poi/hssf/util/HSSFCellRangeAddress.java b/src/java/org/apache/poi/hssf/util/HSSFCellRangeAddress.java
new file mode 100644
index 0000000000..438f5e5968
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/util/HSSFCellRangeAddress.java
@@ -0,0 +1,253 @@
+/* ====================================================================
+ Copyright 2002-2004 Apache Software Foundation
+
+ Licensed 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.util.LittleEndian;
+import java.util.ArrayList;
+
+/**
+ * <p>Title: HSSFCellRangeAddress</p>
+ * <p>Description:
+ * Implementation of the cell range address lists,like is described in
+ * OpenOffice.org's Excel Documentation .
+ * In BIFF8 there is a common way to store absolute cell range address
+ * lists in several records (not formulas). A cell range address list
+ * consists of a field with the number of ranges and the list of the range
+ * addresses. Each cell range address (called an ADDR structure) contains
+ * 4 16-bit-values.</p>
+ * <p>Copyright: Copyright (c) 2004</p>
+ * <p>Company: </p>
+ * @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
+ * @version 2.0-pre
+ */
+
+public class HSSFCellRangeAddress
+{
+ /**
+ * Number of following ADDR structures
+ */
+ private short field_addr_number;
+
+ /**
+ * List of ADDR structures. Each structure represents a cell range
+ */
+ private ArrayList field_regions_list;
+
+ public HSSFCellRangeAddress()
+ {
+
+ }
+
+ /**
+ * Construct a new HSSFCellRangeAddress object and sets its fields appropriately .
+ * Even this isn't an Excel record , I kept the same behavior for reading/writing
+ * the object's data as for a regular record .
+ *
+ * @param in the RecordInputstream to read the record from
+ */
+ public HSSFCellRangeAddress(RecordInputStream in)
+ {
+ this.fillFields(in);
+ }
+
+ public void fillFields(RecordInputStream in)
+ {
+ this.field_addr_number = in.readShort();
+ this.field_regions_list = new ArrayList(this.field_addr_number);
+
+ for (int k = 0; k < this.field_addr_number; k++)
+ {
+ short first_row = in.readShort();
+ short first_col = in.readShort();
+ short last_row = in.readShort();
+ short last_col = in.readShort();
+
+ AddrStructure region = new AddrStructure(first_row, first_col, last_row, last_col);
+ this.field_regions_list.add(region);
+ }
+ }
+
+ /**
+ * Get the number of following ADDR structures.
+ * The number of this structures is automatically set when reading an Excel file
+ * and/or increased when you manually add a new ADDR structure .
+ * This is the reason there isn't a set method for this field .
+ * @return number of ADDR structures
+ */
+ public short getADDRStructureNumber()
+ {
+ return this.field_addr_number;
+ }
+
+ /**
+ * Add an ADDR structure .
+ * @param first_row - the upper left hand corner's row
+ * @param first_col - the upper left hand corner's col
+ * @param last_row - the lower right hand corner's row
+ * @param last_col - the lower right hand corner's col
+ * @return the index of this ADDR structure
+ */
+ public int addADDRStructure(short first_row, short first_col, short last_row, short last_col)
+ {
+ if (this.field_regions_list == null)
+ {
+ //just to be sure :-)
+ this.field_addr_number= 0;
+ this.field_regions_list = new ArrayList(10);
+ }
+ AddrStructure region = new AddrStructure(first_row, last_row, first_col, last_col);
+
+ this.field_regions_list.add(region);
+ this.field_addr_number++;
+ return this.field_addr_number;
+ }
+
+ /**
+ * Remove the ADDR structure stored at the passed in index
+ * @param index The ADDR structure's index
+ */
+ public void removeADDRStructureAt(int index)
+ {
+ this.field_regions_list.remove(index);
+ this.field_addr_number--;
+ }
+
+ /**
+ * return the ADDR structure at the given index.
+ * @return AddrStructure representing
+ */
+ public AddrStructure getADDRStructureAt(int index)
+ {
+ return ( AddrStructure ) this.field_regions_list.get(index);
+ }
+
+ public int serialize(int offset, byte [] data)
+ {
+ int pos = 2;
+
+ LittleEndian.putShort(data, offset, this.getADDRStructureNumber());
+ for (int k = 0; k < this.getADDRStructureNumber(); k++)
+ {
+ AddrStructure region = this.getADDRStructureAt(k);
+ LittleEndian.putShort(data, offset + pos, region.getFirstRow());
+ pos += 2;
+ LittleEndian.putShort(data, offset + pos, region.getLastRow());
+ pos += 2;
+ LittleEndian.putShort(data, offset + pos, region.getFirstColumn());
+ pos += 2;
+ LittleEndian.putShort(data, offset + pos, region.getLastColumn());
+ pos += 2;
+ }
+ return this.getSize();
+ }
+
+ public int getSize()
+ {
+ return 2 + this.field_addr_number*8;
+ }
+
+ public class AddrStructure
+ {
+ private short _first_row;
+ private short _first_col;
+ private short _last_row;
+ private short _last_col;
+
+ public AddrStructure(short first_row, short last_row, short first_col, short last_col)
+ {
+ this._first_row = first_row;
+ this._last_row = last_row;
+ this._first_col = first_col;
+ this._last_col = last_col;
+ }
+
+ /**
+ * get the upper left hand corner column number
+ * @return column number for the upper left hand corner
+ */
+ public short getFirstColumn()
+ {
+ return this._first_col;
+ }
+
+ /**
+ * get the upper left hand corner row number
+ * @return row number for the upper left hand corner
+ */
+ public short getFirstRow()
+ {
+ return this._first_row;
+ }
+
+ /**
+ * get the lower right hand corner column number
+ * @return column number for the lower right hand corner
+ */
+ public short getLastColumn()
+ {
+ return this._last_col;
+ }
+
+ /**
+ * get the lower right hand corner row number
+ * @return row number for the lower right hand corner
+ */
+ public short getLastRow()
+ {
+ return this._last_row;
+ }
+
+ /**
+ * set the upper left hand corner column number
+ * @param this._first_col column number for the upper left hand corner
+ */
+ public void setFirstColumn(short first_col)
+ {
+ this._first_col = first_col;
+ }
+
+ /**
+ * set the upper left hand corner row number
+ * @param rowFrom row number for the upper left hand corner
+ */
+ public void setFirstRow(short first_row)
+ {
+ this._first_row = first_row;
+ }
+
+ /**
+ * set the lower right hand corner column number
+ * @param colTo column number for the lower right hand corner
+ */
+ public void setLastColumn(short last_col)
+ {
+ this._last_col = last_col;
+ }
+
+ /**
+ * get the lower right hand corner row number
+ * @param rowTo row number for the lower right hand corner
+ */
+ public void setLastRow(short last_row)
+ {
+ this._last_row = last_row;
+ }
+ }
+}
+
+
diff --git a/src/java/org/apache/poi/hssf/util/HSSFDataValidation.java b/src/java/org/apache/poi/hssf/util/HSSFDataValidation.java
new file mode 100644
index 0000000000..af578bee48
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/util/HSSFDataValidation.java
@@ -0,0 +1,471 @@
+/* ====================================================================
+ Copyright 2002-2004 Apache Software Foundation
+
+ Licensed 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;
+
+/**
+ * <p>Title: HSSFDataValidation</p>
+ * <p>Description: Utilty class for creating data validation cells</p>
+ * <p>Copyright: Copyright (c) 2004</p>
+ * <p>Company: </p>
+ * @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
+ * @version 2.0-pre
+ */
+
+public class HSSFDataValidation
+{
+ /**
+ * Validation data type constants
+ */
+ /**
+ * Any type
+ */
+ public static final int DATA_TYPE_ANY = 0x00;
+ /**
+ * Integer type
+ */
+ public static final int DATA_TYPE_INTEGER = 0x01;
+ /**
+ * Decimal type
+ */
+ public static final int DATA_TYPE_DECIMAL = 0x02;
+ /**
+ * List type ( combo box type )
+ */
+ public static final int DATA_TYPE_LIST = 0x03;
+ /**
+ * Date type
+ */
+ public static final int DATA_TYPE_DATE = 0x04;
+ /**
+ * Time type
+ */
+ public static final int DATA_TYPE_TIME = 0x05;
+ /**
+ * String length type
+ */
+ public static final int DATA_TYPE_TEXT_LENGTH = 0x06;
+ /**
+ * Formula ( custom ) type
+ */
+ public static final int DATA_TYPE_FORMULA = 0x07;
+
+ /**
+ * Error style constants for error box
+ */
+ /**
+ * STOP style like
+ */
+ public static final int ERROR_STYLE_STOP = 0x00;
+ /**
+ * WARNING style like
+ */
+ public static final int ERROR_STYLE_WARNING = 0x01;
+ /**
+ * INFO style like
+ */
+ public static final int ERROR_STYLE_INFO = 0x02;
+
+ /**
+ * Condition operator
+ */
+ public static final int OPERATOR_BETWEEN = 0x00;
+ public static final int OPERATOR_NOT_BETWEEN = 0x01;
+ public static final int OPERATOR_EQUAL = 0x02;
+ public static final int OPERATOR_NOT_EQUAL = 0x03;
+ public static final int OPERATOR_GREATER_THAN = 0x04;
+ public static final int OPERATOR_LESS_THAN = 0x05;
+ public static final int OPERATOR_GREATER_OR_EQUAL = 0x06;
+ public static final int OPERATOR_LESS_OR_EQUAL = 0x07;
+
+ private short _first_row = 0;
+ private short _first_col = 0;
+ private short _last_row = 0;
+ private short _last_col = 0;
+
+ private String _prompt_title = null;
+ private String _prompt_text = null;
+ private String _error_title = null;
+ private String _error_text = null;
+ private String _string_first_formula = null;
+ private String _string_sec_formula = null;
+
+ private int _data_type = HSSFDataValidation.DATA_TYPE_ANY;
+ private int _error_style = HSSFDataValidation.ERROR_STYLE_STOP;
+ private boolean _list_explicit_formula = true;
+ private boolean _empty_cell_allowed = true;
+ private boolean _surpress_dropdown_arrow = false;
+ private boolean _show_prompt_box = true;
+ private boolean _show_error_box = true;
+ private int _operator = HSSFDataValidation.OPERATOR_BETWEEN;
+
+
+ /**
+ * Empty constructor
+ */
+ public HSSFDataValidation( )
+ {
+ }
+
+ /**
+ * Constructor wich initializes the cell range on wich this object will be applied
+ * @param first_row First row
+ * @param first_col First column
+ * @param last_row Last row
+ * @param last_col Last column
+ */
+ public HSSFDataValidation( short first_row, short first_col, short last_row, short last_col )
+ {
+ this._first_row = first_row;
+ this._first_col = first_col;
+ this._last_row = last_row;
+ this._last_col = last_col;
+ }
+
+ /**
+ * Set the type of this object
+ * @param data_type The type
+ * @see DATA_TYPE_ANY, DATA_TYPE_INTEGER, DATA_TYPE_DECIMNAL, DATA_TYPE_LIST, DATA_TYPE_DATE,
+ * DATA_TYPE_TIME, DATA_TYPE_TEXT_LENTGH, DATA_TYPE_FORMULA
+ */
+ public void setDataValidationType( int data_type )
+ {
+ this._data_type = data_type;
+ }
+
+ /**
+ * The data type of this object
+ * @return The type
+ * @see DATA_TYPE_ANY, DATA_TYPE_INTEGER, DATA_TYPE_DECIMNAL, DATA_TYPE_LIST, DATA_TYPE_DATE,
+ * DATA_TYPE_TIME, DATA_TYPE_TEXT_LENTGH, DATA_TYPE_FORMULA
+ */
+ public int getDataValidationType()
+ {
+ return this._data_type;
+ }
+
+ /**
+ * Sets the error style for error box
+ * @param error_style Error style constant
+ * @see ERROR_STYLE_STOP, ERROR_STYLE_WARNING, ERROR_STYLE_INFO
+ */
+ public void setErrorStyle( int error_style )
+ {
+ this._error_style = error_style;
+ }
+
+ /**
+ * returns the error style of errror box
+ * @return the style constant
+ * @see ERROR_STYLE_STOP, ERROR_STYLE_WARNING, ERROR_STYLE_INFO
+ */
+ public int getErrorStyle( )
+ {
+ return this._error_style;
+ }
+
+ /**
+ * If this object has an explicit formula . This is useful only for list data validation object
+ * @param explicit True if use an explicit formula
+ */
+ public void setExplicitListFormula( boolean explicit )
+ {
+ this._list_explicit_formula = explicit;
+ }
+
+ /**
+ * Returns the settings for explicit formula . This is useful only for list data validation objects.
+ * This method always returns false if the object isn't a list validation object
+ * @see setDataValidationType( int data_type )
+ * @return
+ */
+ public boolean getExplicitListFormula( )
+ {
+ if ( this._data_type != HSSFDataValidation.DATA_TYPE_LIST )
+ {
+ return false;
+ }
+ return this._list_explicit_formula ;
+ }
+
+ /**
+ * Sets if this object allows empty as a valid value
+ * @param allowed True if this object should treats empty as valid value , false otherwise
+ */
+ public void setEmptyCellAllowed( boolean allowed )
+ {
+ this._empty_cell_allowed = allowed;
+ }
+
+ /**
+ * Retrieve the settings for empty cells allowed
+ * @return True if this object should treats empty as valid value , false otherwise
+ */
+ public boolean getEmptyCellAllowed( )
+ {
+ return this._empty_cell_allowed ;
+ }
+
+ /**
+ * Useful for list validation objects .
+ * @param surppres True if a list should display the values into a drop down list , false otherwise .
+ * In other words , if a list should display the arrow sign on its right side
+ */
+ public void setSurppressDropDownArrow( boolean surppres )
+ {
+ this._surpress_dropdown_arrow = surppres;
+ }
+
+ /**
+ * Useful only list validation objects .
+ * This method always returns false if the object isn't a list validation object
+ * @return True if a list should display the values into a drop down list , false otherwise .
+ * @see setDataValidationType( int data_type )
+ */
+ public boolean getSurppressDropDownArrow( )
+ {
+ if ( this._data_type != HSSFDataValidation.DATA_TYPE_LIST )
+ {
+ return false;
+ }
+ return this._surpress_dropdown_arrow ;
+ }
+
+ /**
+ * Sets the behaviour when a cell which belongs to this object is selected
+ * @param show True if an prompt box should be displayed , false otherwise
+ */
+ public void setShowPromptBox( boolean show )
+ {
+ this._show_prompt_box = show;
+ }
+
+ /**
+ * @param show True if an prompt box should be displayed , false otherwise
+ */
+ public boolean getShowPromptBox( )
+ {
+ if ( (this.getPromptBoxText() == null) && (this.getPromptBoxTitle() == null) )
+ {
+ return false;
+ }
+ return this._show_prompt_box ;
+ }
+
+ /**
+ * Sets the behaviour when an invalid value is entered
+ * @param show True if an error box should be displayed , false otherwise
+ */
+ public void setShowErrorBox( boolean show )
+ {
+ this._show_error_box = show;
+ }
+
+ /**
+ * @return True if an error box should be displayed , false otherwise
+ */
+ public boolean getShowErrorBox( )
+ {
+ if ( (this.getErrorBoxText() == null) && (this.getErrorBoxTitle() == null) )
+ {
+ return false;
+ }
+ return this._show_error_box ;
+ }
+
+ /**
+ * Sets the operator involved in the formula whic governs this object
+ * Example : if you wants that a cell to accept only values between 1 and 5 , which
+ * mathematically means 1 <= value <= 5 , then the operator should be OPERATOR_BETWEEN
+ * @param operator A constant for operator
+ * @see OPERATOR_BETWEEN, OPERATOR_NOT_BETWEEN, OPERATOR_EQUAL, OPERATOR_NOT_EQUAL
+ * OPERATOR_GREATER_THAN, OPERATOR_LESS_THAN, OPERATOR_GREATER_OR_EQUAL,
+ * OPERATOR_LESS_OR_EQUAL
+ */
+ public void setOperator( int operator )
+ {
+ this._operator = operator;
+ }
+
+ /**
+ * Retrieves the operator used for this object's formula
+ * @return
+ * @see OPERATOR_BETWEEN, OPERATOR_NOT_BETWEEN, OPERATOR_EQUAL, OPERATOR_NOT_EQUAL
+ * OPERATOR_GREATER_THAN, OPERATOR_LESS_THAN, OPERATOR_GREATER_OR_EQUAL,
+ * OPERATOR_LESS_OR_EQUAL
+ */
+ public int getOperator()
+ {
+ return this._operator;
+ }
+
+ /**
+ * Sets the title and text for the prompt box . Prompt box is displayed when the user
+ * selects a cell which belongs to this validation object . In order for a prompt box
+ * to be displayed you should also use method setShowPromptBox( boolean show )
+ * @param title The prompt box's title
+ * @param text The prompt box's text
+ * @see setShowPromptBox( boolean show )
+ */
+ public void createPromptBox( String title, String text )
+ {
+ this._prompt_title = title;
+ this._prompt_text = text;
+ this.setShowPromptBox(true);
+ }
+
+ /**
+ * Returns the prompt box's title
+ * @return Prompt box's title or null
+ */
+ public String getPromptBoxTitle( )
+ {
+ return this._prompt_title;
+ }
+
+ /**
+ * Returns the prompt box's text
+ * @return Prompt box's text or null
+ */
+ public String getPromptBoxText( )
+ {
+ return this._prompt_text;
+ }
+
+ /**
+ * Sets the title and text for the error box . Error box is displayed when the user
+ * enters an invalid value int o a cell which belongs to this validation object .
+ * In order for an error box to be displayed you should also use method
+ * setShowErrorBox( boolean show )
+ * @param title The error box's title
+ * @param text The error box's text
+ * @see setShowErrorBox( boolean show )
+ */
+ public void createErrorBox( String title, String text )
+ {
+ this._error_title = title;
+ this._error_text = text;
+ this.setShowErrorBox(true);
+ }
+
+ /**
+ * Returns the error box's title
+ * @return Error box's title or null
+ */
+ public String getErrorBoxTitle( )
+ {
+ return this._error_title;
+ }
+
+ /**
+ * Returns the error box's text
+ * @return Error box's text or null
+ */
+ public String getErrorBoxText( )
+ {
+ return this._error_text;
+ }
+
+ /**
+ * Sets the first formula for this object .
+ * A formula is divided into three parts : first formula , operator and second formula .
+ * In other words , a formula contains a left oprand , an operator and a right operand.
+ * This is the general rule . An example is 1<= value <= 5 . In this case ,
+ * the left operand ( or the first formula ) is the number 1 . The operator is
+ * OPERATOR_BETWEEN and the right operand ( or the second formula ) is 5 .
+ * @param formula
+ */
+ public void setFirstFormula( String formula )
+ {
+ this._string_first_formula = formula;
+ }
+
+ /**
+ * Returns the first formula
+ * @return
+ */
+ public String getFirstFormula( )
+ {
+ return this._string_first_formula;
+ }
+
+ /**
+ * Sets the first formula for this object .
+ * A formula is divided into three parts : first formula , operator and second formula .
+ * In other words , a formula contains a left oprand , an operator and a right operand.
+ * This is the general rule . An example is 1<= value <=5 . In this case ,
+ * the left operand ( or the first formula ) is the number 1 . The operator is
+ * OPERATOR_BETWEEN and the right operand ( or the second formula ) is 5 .
+ * But there are cases when a second formula isn't needed :
+ * You want somethink like : all values less than 5 . In this case , there's only a first
+ * formula ( in our case 5 ) and the operator OPERATOR_LESS_THAN
+ * @param formula
+ */
+ public void setSecondFormula( String formula )
+ {
+ this._string_sec_formula = formula;
+ }
+
+ /**
+ * Returns the second formula
+ * @return
+ */
+ public String getSecondFormula( )
+ {
+ return this._string_sec_formula;
+ }
+
+ public void setFirstRow( short first_row )
+ {
+ this._first_row = first_row;
+ }
+
+ public void setFirstColumn( short first_column )
+ {
+ this._first_col = first_column;
+ }
+
+ public void setLastRow( short last_row )
+ {
+ this._last_row = last_row;
+ }
+
+ public void setLastColumn( short last_column )
+ {
+ this._last_col = last_column;
+ }
+
+ public short getFirstRow()
+ {
+ return this._first_row;
+ }
+
+ public short getFirstColumn()
+ {
+ return this._first_col;
+ }
+
+ public short getLastRow()
+ {
+ return this._last_row;
+ }
+
+ public short getLastColumn()
+ {
+ return this._last_col;
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java b/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java
index f5bb58a76f..4f89af1545 100644
--- a/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java
+++ b/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java
@@ -19,6 +19,7 @@
package org.apache.poi.poifs.storage;
+import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.BATManaged;
import org.apache.poi.poifs.filesystem.POIFSDocument;
import org.apache.poi.poifs.property.RootProperty;
@@ -69,6 +70,8 @@ public class SmallBlockTableWriter
{
_small_blocks.add(blocks[ j ]);
}
+ } else {
+ doc.setStartBlock(POIFSConstants.END_OF_CHAIN);
}
}
_sbat.simpleCreateBlocks();
diff --git a/src/java/org/apache/poi/util/IOUtils.java b/src/java/org/apache/poi/util/IOUtils.java
index 7126b2b9be..42b69c850b 100644
--- a/src/java/org/apache/poi/util/IOUtils.java
+++ b/src/java/org/apache/poi/util/IOUtils.java
@@ -19,6 +19,7 @@
package org.apache.poi.util;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -29,6 +30,25 @@ public class IOUtils
}
/**
+ * Reads all the data from the input stream, and returns
+ * the bytes read.
+ */
+ public static byte[] toByteArray(InputStream stream) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ byte[] buffer = new byte[4096];
+ int read = 0;
+ while(read != -1) {
+ read = stream.read(buffer);
+ if(read > 0) {
+ baos.write(buffer, 0, read);
+ }
+ }
+
+ return baos.toByteArray();
+ }
+
+ /**
* Helper method, just calls <tt>readFully(in, b, 0, b.length)</tt>
*/
public static int readFully(InputStream in, byte[] b)
diff --git a/src/java/org/apache/poi/util/StringUtil.java b/src/java/org/apache/poi/util/StringUtil.java
index 9dd8e4838e..673b5246e1 100644
--- a/src/java/org/apache/poi/util/StringUtil.java
+++ b/src/java/org/apache/poi/util/StringUtil.java
@@ -161,7 +161,8 @@ public class StringUtil {
final int offset,
final int len) {
try {
- return new String(string, offset, len, "ISO-8859-1");
+ int len_to_use = Math.min(len, string.length - offset);
+ return new String(string, offset, len_to_use, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
throw new InternalError(); /* unreachable */
}