diff options
Diffstat (limited to 'src/java/org/apache')
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 */ } |