<!-- Don't forget to update status.xml too! -->
<release version="3.1.1-alpha1" date="2008-??-??">
+ <action dev="POI-DEVELOPERS" type="fix">44953 - Extensive fixes for data validation</action>
<action dev="POI-DEVELOPERS" type="fix">45519 - Fixed to keep datavalidation records together</action>
<action dev="POI-DEVELOPERS" type="add">Support for creating new HSLF CurrentUserAtoms</action>
<action dev="POI-DEVELOPERS" type="add">45466 - Partial support for removing excel comments (won't work for all excel versions yet)</action>
<!-- Don't forget to update changes.xml too! -->
<changes>
<release version="3.1.1-alpha1" date="2008-??-??">
+ <action dev="POI-DEVELOPERS" type="fix">44953 - Extensive fixes for data validation</action>
<action dev="POI-DEVELOPERS" type="fix">45519 - Fixed to keep datavalidation records together</action>
<action dev="POI-DEVELOPERS" type="add">Support for creating new HSLF CurrentUserAtoms</action>
<action dev="POI-DEVELOPERS" type="add">45466 - Partial support for removing excel comments (won't work for all excel versions yet)</action>
public static final int FORMULA_TYPE_CELL = 0;
public static final int FORMULA_TYPE_SHARED = 1;
public static final int FORMULA_TYPE_ARRAY =2;
- public static final int FORMULA_TYPE_CONDFOMRAT = 3;
+ public static final int FORMULA_TYPE_CONDFORMAT = 3;
public static final int FORMULA_TYPE_NAMEDRANGE = 4;
+ // this constant is currently very specific. The exact differences from general data
+ // validation formulas or conditional format formulas is not known yet
+ public static final int FORMULA_TYPE_DATAVALIDATION_LIST = 5;
private final String formulaString;
private final int formulaLength;
private ParseNode _rootNode;
- /**
- * Used for spotting if we have a cell reference,
- * or a named range
- */
- private final static Pattern CELL_REFERENCE_PATTERN = Pattern.compile("(?:('?)[^:\\\\/\\?\\*\\[\\]]+\\1!)?\\$?[A-Za-z]+\\$?[\\d]+");
-
private static char TAB = '\t';
/**
}
public static Ptg[] parse(String formula, HSSFWorkbook book) {
- FormulaParser fp = new FormulaParser(formula, book);
+ return parse(formula, book, FORMULA_TYPE_CELL);
+ }
+
+ public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType) {
+ FormulaParser fp = new FormulaParser(formula, workbook);
fp.parse();
- return fp.getRPNPtg();
+ return fp.getRPNPtg(formulaType);
}
/** Read New Character From Input Stream */
case FormulaParser.FORMULA_TYPE_CELL:
rootNodeOperandClass = Ptg.CLASS_VALUE;
break;
+ case FormulaParser.FORMULA_TYPE_DATAVALIDATION_LIST:
+ rootNodeOperandClass = Ptg.CLASS_REF;
+ break;
default:
throw new RuntimeException("Incomplete code - formula type ("
+ _formulaType + ") not supported yet");
package org.apache.poi.hssf.record;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Stack;
-
+import org.apache.poi.hssf.record.UnicodeString.UnicodeRecordStats;
import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.util.HSSFCellRangeAddress;
-import org.apache.poi.hssf.util.HSSFCellRangeAddress.AddrStructure;
+import org.apache.poi.hssf.usermodel.DVConstraint;
+import org.apache.poi.hssf.usermodel.HSSFDataValidation;
+import org.apache.poi.hssf.util.CellRangeAddress;
+import org.apache.poi.hssf.util.CellRangeAddressList;
import org.apache.poi.util.BitField;
import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.StringUtil;
/**
* Title: DATAVALIDATION Record (0x01BE)<p/>
* 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
+ * @author Josh Micich
*/
-public final 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_suppress_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
- 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
- if (false) { // TODO - prior to bug 44710 this 'skip' was being executed. write a junit to confirm this fix
- try {
- in.skip(this.field_size_sec_formula);
- } catch(IOException e) {
- e.printStackTrace();
- throw new IllegalStateException(e.getMessage());
- }
- }
- 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));
- }
- /**
- * @deprecated - (Jul-2008) use setSuppressDropDownArrow
- */
- public void setSurppresDropdownArrow(boolean suppress) {
- setSuppressDropdownArrow(suppress);
- }
- /**
- * @deprecated - (Jul-2008) use getSuppressDropDownArrow
- */
- public boolean getSurppresDropdownArrow() {
- return getSuppressDropdownArrow();
- }
-
- /**
- * set if drop down arrow should be suppressed when list validation is used
- * @param type - true if drop down arrow should be suppressed when list validation is used, false otherwise
- * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
- */
- public void setSuppressDropdownArrow(boolean suppress)
- {
- this.field_option_flags = this.opt_suppress_dropdown_arrow.setBoolean(this.field_option_flags, suppress);
- }
-
- /**
- * return true if drop down arrow should be suppressed when list validation is used, false otherwise
- * @return if drop down arrow should be suppressed when list validation is used, false otherwise
- * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
- */
- public boolean getSuppressDropdownArrow()
- {
- return (this.opt_suppress_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 sb = new StringBuffer();
- sb.append("[DV]\n");
- sb.append(" options=").append(Integer.toHexString(field_option_flags));
- sb.append(" title-prompt=").append(field_title_prompt);
- sb.append(" title-error=").append(field_title_error);
- sb.append(" text-prompt=").append(field_text_prompt);
- sb.append(" text-error=").append(field_text_error);
- sb.append("\n");
- appendFormula(sb, "Formula 1:", field_rpn_token_1);
- appendFormula(sb, "Formula 2:", field_rpn_token_2);
- int nRegions = field_regions.getADDRStructureNumber();
- for(int i=0; i<nRegions; i++) {
- AddrStructure addr = field_regions.getADDRStructureAt(i);
- sb.append('(').append(addr.getFirstRow()).append(',').append(addr.getLastRow());
- sb.append(',').append(addr.getFirstColumn()).append(',').append(addr.getLastColumn()).append(')');
- }
- sb.append("\n");
- sb.append("[/DV]");
-
- return sb.toString();
- }
-
- private void appendFormula(StringBuffer sb, String label, Stack stack) {
- sb.append(label);
- if (stack.isEmpty()) {
- sb.append("<empty>\n");
- return;
- }
- sb.append("\n");
- Ptg[] ptgs = new Ptg[stack.size()];
- stack.toArray(ptgs);
- for (int i = 0; i < ptgs.length; i++) {
- sb.append('\t').append(ptgs[i].toString()).append('\n');
- }
- }
-
- 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;
- }
-
- /**
- * Clones the object. Uses serialisation, as the
- * contents are somewhat complex
- */
- public Object clone() {
- return cloneViaReserialise();
- }
-
- /**@todo DVRecord = Serializare */
-
- private static final 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();
- }
- }
+public final class DVRecord extends Record {
+ public final static short sid = 0x01BE;
+
+ /** the unicode string used for error/prompt title/text when not present */
+ private static final UnicodeString NULL_TEXT_STRING = new UnicodeString("\0");
+
+ /** Option flags */
+ private int _option_flags;
+ /** Title of the prompt box */
+ private UnicodeString _promptTitle;
+ /** Title of the error box */
+ private UnicodeString _errorTitle;
+ /** Text of the prompt box */
+ private UnicodeString _promptText;
+ /** Text of the error box */
+ private UnicodeString _errorText;
+ /** Not used - Excel seems to always write 0x3FE0 */
+ private short _not_used_1 = 0x3FE0;
+ /** Formula data for first condition (RPN token array without size field) */
+ private Ptg[] _formula1;
+ /** Not used - Excel seems to always write 0x0000 */
+ private short _not_used_2 = 0x0000;
+ /** Formula data for second condition (RPN token array without size field) */
+ private Ptg[] _formula2;
+ /** Cell range address list with all affected ranges */
+ private CellRangeAddressList _regions;
+
+ /**
+ * Option flags field
+ *
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ private static final BitField opt_data_type = new BitField(0x0000000F);
+ private static final BitField opt_error_style = new BitField(0x00000070);
+ private static final BitField opt_string_list_formula = new BitField(0x00000080);
+ private static final BitField opt_empty_cell_allowed = new BitField(0x00000100);
+ private static final BitField opt_suppress_dropdown_arrow = new BitField(0x00000200);
+ private static final BitField opt_show_prompt_on_cell_selected = new BitField(0x00040000);
+ private static final BitField opt_show_error_on_invalid_value = new BitField(0x00080000);
+ private static final BitField opt_condition_operator = new BitField(0x00700000);
+
+ /**
+ * Constructs a DV record and sets its fields appropriately.
+ *
+ * @param in the RecordInputstream to read the record from
+ */
+ public DVRecord(RecordInputStream in) {
+ super(in);
+ }
+
+ public DVRecord(int validationType, int operator, int errorStyle, boolean emptyCellAllowed,
+ boolean suppressDropDownArrow, boolean isExplicitList,
+ boolean showPromptBox, String promptTitle, String promptText,
+ boolean showErrorBox, String errorTitle, String errorText,
+ Ptg[] formula1, Ptg[] formula2,
+ CellRangeAddressList regions) {
+
+ int flags = 0;
+ flags = opt_data_type.setValue(flags, validationType);
+ flags = opt_condition_operator.setValue(flags, operator);
+ flags = opt_error_style.setValue(flags, errorStyle);
+ flags = opt_empty_cell_allowed.setBoolean(flags, emptyCellAllowed);
+ flags = opt_suppress_dropdown_arrow.setBoolean(flags, suppressDropDownArrow);
+ flags = opt_string_list_formula.setBoolean(flags, isExplicitList);
+ flags = opt_show_prompt_on_cell_selected.setBoolean(flags, showPromptBox);
+ flags = opt_show_error_on_invalid_value.setBoolean(flags, showErrorBox);
+ _option_flags = flags;
+ _promptTitle = resolveTitleText(promptTitle);
+ _promptText = resolveTitleText(promptText);
+ _errorTitle = resolveTitleText(errorTitle);
+ _errorText = resolveTitleText(errorText);
+ _formula1 = formula1;
+ _formula2 = formula2;
+ _regions = regions;
+ }
+
+ protected void validateSid(short id) {
+ if (id != sid) {
+ throw new RecordFormatException("NOT a valid DV RECORD");
+ }
+ }
+
+ protected void fillFields(RecordInputStream in) {
+
+ _option_flags = in.readInt();
+
+ _promptTitle = readUnicodeString(in);
+ _errorTitle = readUnicodeString(in);
+ _promptText = readUnicodeString(in);
+ _errorText = readUnicodeString(in);
+
+ int field_size_first_formula = in.readUShort();
+ _not_used_1 = in.readShort();
+
+ //read first formula data condition
+ _formula1 = Ptg.readTokens(field_size_first_formula, in);
+
+ int field_size_sec_formula = in.readUShort();
+ _not_used_2 = in.readShort();
+
+ //read sec formula data condition
+ _formula2 = Ptg.readTokens(field_size_sec_formula, in);
+
+ //read cell range address list with all affected ranges
+ _regions = new CellRangeAddressList(in);
+ }
+
+ // --> start option flags
+ /**
+ * @return the condition data type
+ * @see DVConstraint.ValidationType
+ */
+ public int getDataType() {
+ return opt_data_type.getValue(_option_flags);
+ }
+
+ /**
+ * @return the condition error style
+ * @see HSSFDataValidation.ErrorStyle
+ */
+ public int getErrorStyle() {
+ return opt_error_style.getValue(_option_flags);
+ }
+
+ /**
+ * @return <code>true</code> if in list validations the string list is explicitly given in the
+ * formula, <code>false</code> otherwise
+ */
+ public boolean getListExplicitFormula() {
+ return (opt_string_list_formula.isSet(_option_flags));
+ }
+
+ /**
+ * @return <code>true</code> if empty values are allowed in cells, <code>false</code> otherwise
+ */
+ public boolean getEmptyCellAllowed() {
+ return (opt_empty_cell_allowed.isSet(_option_flags));
+ }
+
+
+ /**
+ * @return <code>true</code> if drop down arrow should be suppressed when list validation is
+ * used, <code>false</code> otherwise
+ */
+ public boolean getSuppressDropdownArrow() {
+ return (opt_suppress_dropdown_arrow.isSet(_option_flags));
+ }
+
+ /**
+ * @return <code>true</code> if a prompt window should appear when cell is selected, <code>false</code> otherwise
+ */
+ public boolean getShowPromptOnCellSelected() {
+ return (opt_show_prompt_on_cell_selected.isSet(_option_flags));
+ }
+
+ /**
+ * @return <code>true</code> if an error window should appear when an invalid value is entered
+ * in the cell, <code>false</code> otherwise
+ */
+ public boolean getShowErrorOnInvalidValue() {
+ return (opt_show_error_on_invalid_value.isSet(_option_flags));
+ }
+
+ /**
+ * get the condition operator
+ * @return the condition operator
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public int getConditionOperator() {
+ return opt_condition_operator.getValue(_option_flags);
+ }
+ // <-- end option flags
+
+
+
+
+ public CellRangeAddressList getCellRangeAddress() {
+ return this._regions;
+ }
+
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[DV]\n");
+ sb.append(" options=").append(Integer.toHexString(_option_flags));
+ sb.append(" title-prompt=").append(formatTextTitle(_promptTitle));
+ sb.append(" title-error=").append(formatTextTitle(_errorTitle));
+ sb.append(" text-prompt=").append(formatTextTitle(_promptText));
+ sb.append(" text-error=").append(formatTextTitle(_errorText));
+ sb.append("\n");
+ appendFormula(sb, "Formula 1:", _formula1);
+ appendFormula(sb, "Formula 2:", _formula2);
+ sb.append("Regions: ");
+ int nRegions = _regions.getADDRStructureNumber();
+ for(int i=0; i<nRegions; i++) {
+ if (i>0) {
+ sb.append(", ");
+ }
+ CellRangeAddress addr = _regions.getCellRangeAddress(i);
+ sb.append('(').append(addr.getFirstRow()).append(',').append(addr.getLastRow());
+ sb.append(',').append(addr.getFirstColumn()).append(',').append(addr.getLastColumn()).append(')');
+ }
+ sb.append("\n");
+ sb.append("[/DV]");
+
+ return sb.toString();
+ }
+
+ private static String formatTextTitle(UnicodeString us) {
+ String str = us.getString();
+ if (str.length() == 1 && str.charAt(0) == '\0') {
+ return "'\\0'";
+ }
+ return str;
+ }
+
+ private void appendFormula(StringBuffer sb, String label, Ptg[] ptgs) {
+ sb.append(label);
+ if (ptgs.length < 1) {
+ sb.append("<empty>\n");
+ return;
+ }
+ sb.append("\n");
+ for (int i = 0; i < ptgs.length; i++) {
+ sb.append('\t').append(ptgs[i].toString()).append('\n');
+ }
+ }
+
+ 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, _option_flags);
+ pos += 4;
+
+ pos += serializeUnicodeString(_promptTitle, pos+offset, data);
+ pos += serializeUnicodeString(_errorTitle, pos+offset, data);
+ pos += serializeUnicodeString(_promptText, pos+offset, data);
+ pos += serializeUnicodeString(_errorText, pos+offset, data);
+ LittleEndian.putUShort(data, offset+pos, Ptg.getEncodedSize(_formula1));
+ pos += 2;
+ LittleEndian.putUShort(data, offset+pos, _not_used_1);
+ pos += 2;
+
+ pos += Ptg.serializePtgs(_formula1, data, pos+offset);
+
+ LittleEndian.putUShort(data, offset+pos, Ptg.getEncodedSize(_formula2));
+ pos += 2;
+ LittleEndian.putShort(data, offset+pos, _not_used_2);
+ pos += 2;
+ pos += Ptg.serializePtgs(_formula2, data, pos+offset);
+ _regions.serialize(pos+offset, data);
+ return size;
+ }
+
+ /**
+ * When entered via the UI, Excel translates empty string into "\0"
+ * While it is possible to encode the title/text as empty string (Excel doesn't exactly crash),
+ * the resulting tool-tip text / message box looks wrong. It is best to do the same as the
+ * Excel UI and encode 'not present' as "\0".
+ */
+ private static UnicodeString resolveTitleText(String str) {
+ if (str == null || str.length() < 1) {
+ return NULL_TEXT_STRING;
+ }
+ return new UnicodeString(str);
+ }
+
+ private static UnicodeString readUnicodeString(RecordInputStream in) {
+ return new UnicodeString(in);
+ }
+
+ private static int serializeUnicodeString(UnicodeString us, int offset, byte[] data) {
+ UnicodeRecordStats urs = new UnicodeRecordStats();
+ us.serialize(urs, offset, data);
+ return urs.recordSize;
+ }
+ private static int getUnicodeStringSize(UnicodeString str) {
+ return 3 + str.getString().length();
+ }
+
+ public int getRecordSize() {
+ int size = 4+4+2+2+2+2;//header+options_field+first_formula_size+first_unused+sec_formula_size+sec+unused;
+ size += getUnicodeStringSize(_promptTitle);
+ size += getUnicodeStringSize(_errorTitle);
+ size += getUnicodeStringSize(_promptText);
+ size += getUnicodeStringSize(_errorText);
+ size += Ptg.getEncodedSize(_formula1);
+ size += Ptg.getEncodedSize(_formula2);
+ size += _regions.getSize();
+ return size;
+ }
+
+ public short getSid() {
+ return sid;
+ }
+
+ /**
+ * Clones the object. Uses serialisation, as the
+ * contents are somewhat complex
+ */
+ public Object clone() {
+ return cloneViaReserialise();
+ }
}
\r
import java.util.ArrayList;\r
import java.util.List;\r
-import java.util.Stack;\r
\r
-import org.apache.poi.hssf.model.FormulaParser;\r
import org.apache.poi.hssf.model.RecordStream;\r
import org.apache.poi.hssf.record.CFHeaderRecord;\r
import org.apache.poi.hssf.record.CFRuleRecord;\r
import org.apache.poi.hssf.record.Record;\r
import org.apache.poi.hssf.record.SelectionRecord;\r
import org.apache.poi.hssf.record.WindowTwoRecord;\r
-import org.apache.poi.hssf.record.formula.Ptg;\r
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;\r
-import org.apache.poi.hssf.util.HSSFCellRangeAddress;\r
-import org.apache.poi.hssf.util.HSSFDataValidation;\r
\r
/**\r
* Manages the DVALRecord and DVRecords for a single sheet<br/>\r
return false;\r
}\r
\r
- public void addDataValidation(HSSFDataValidation dataValidation, HSSFWorkbook workbook) {\r
-\r
- DVRecord dvRecord = new DVRecord();\r
-\r
- // dv record's option flags\r
- dvRecord.setDataType(dataValidation.getDataValidationType());\r
- dvRecord.setErrorStyle(dataValidation.getErrorStyle());\r
- dvRecord.setEmptyCellAllowed(dataValidation.getEmptyCellAllowed());\r
- dvRecord.setSuppressDropdownArrow(dataValidation.getSuppressDropDownArrow());\r
- dvRecord.setShowPromptOnCellSelected(dataValidation.getShowPromptBox());\r
- dvRecord.setShowErrorOnInvalidValue(dataValidation.getShowErrorBox());\r
- dvRecord.setConditionOperator(dataValidation.getOperator());\r
-\r
- // string fields\r
- dvRecord.setStringField(DVRecord.STRING_PROMPT_TITLE, dataValidation.getPromptBoxTitle());\r
- dvRecord.setStringField(DVRecord.STRING_PROMPT_TEXT, dataValidation.getPromptBoxText());\r
- dvRecord.setStringField(DVRecord.STRING_ERROR_TITLE, dataValidation.getErrorBoxTitle());\r
- dvRecord.setStringField(DVRecord.STRING_ERROR_TEXT, dataValidation.getErrorBoxText());\r
-\r
- // formula fields ( size and data )\r
- Stack ptg_arr = new Stack();\r
- Ptg[] ptg = FormulaParser.parse(dataValidation.getFirstFormula(), workbook);\r
- int size = 0;\r
- for (int k = 0; k < ptg.length; k++) {\r
- if (ptg[k] instanceof org.apache.poi.hssf.record.formula.AreaPtg) {\r
- // we should set ptgClass to Ptg.CLASS_REF and explicit formula\r
- // string to false\r
- // ptg[k].setClass(Ptg.CLASS_REF);\r
- // obj_validation.setExplicitListFormula(false);\r
- }\r
- size += ptg[k].getSize();\r
- ptg_arr.push(ptg[k]);\r
- }\r
- dvRecord.setFirstFormulaRPN(ptg_arr);\r
- dvRecord.setFirstFormulaSize((short) size);\r
-\r
- dvRecord.setListExplicitFormula(dataValidation.getExplicitListFormula());\r
-\r
- if (dataValidation.getSecondFormula() != null) {\r
-\r
- ptg_arr = new Stack();\r
- ptg = FormulaParser.parse(dataValidation.getSecondFormula(), workbook);\r
- size = 0;\r
- for (int k = 0; k < ptg.length; k++) {\r
- size += ptg[k].getSize();\r
- ptg_arr.push(ptg[k]);\r
- }\r
- dvRecord.setSecFormulaRPN(ptg_arr);\r
- dvRecord.setSecFormulaSize((short) size);\r
- }\r
-\r
- // dv records cell range field\r
- HSSFCellRangeAddress cell_range = new HSSFCellRangeAddress();\r
- cell_range.addADDRStructure(dataValidation.getFirstRow(), dataValidation.getFirstColumn(),\r
- dataValidation.getLastRow(), dataValidation.getLastColumn());\r
- dvRecord.setCellRangeAddress(cell_range);\r
-\r
+ public void addDataValidation(DVRecord dvRecord) {\r
_validationList.add(dvRecord);\r
_headerRec.setDVRecNo(_validationList.size());\r
}\r
/** Create a NumberPtg from a byte array read from disk */
public NumberPtg(RecordInputStream in)
{
- field_1_value = in.readDouble();
+ this(in.readDouble());
}
/** Create a NumberPtg from a string representation of the number
* @param value : String representation of a floating point number
*/
public NumberPtg(String value) {
- field_1_value = Double.parseDouble(value);
+ this(Double.parseDouble(value));
}
+ public NumberPtg(double value) {
+ field_1_value = value;
+ }
public double getValue()
{
public String toFormulaString(HSSFWorkbook book)
{
- return "" + getValue();
+ // TODO - java's rendering of double values is not quite same as excel's
+ return String.valueOf(field_1_value);
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer(64);
+ sb.append(getClass().getName()).append(" [");
+ sb.append(field_1_value);
+ sb.append("]");
+ return sb.toString();
}
}
* @author Jason Height (jheight at chariot dot net dot au)
*/
public abstract class Ptg implements Cloneable {
+ public static final Ptg[] EMPTY_PTG_ARRAY = { };
/* convert infix order ptg list to rpn order ptg list
* @return List ptgs in RPN order
}
}
private static Ptg[] toPtgArray(List l) {
+ if (l.isEmpty()) {
+ return EMPTY_PTG_ARRAY;
+ }
Ptg[] result = new Ptg[l.size()];
l.toArray(result);
return result;
--- /dev/null
+/* ====================================================================
+ 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.usermodel;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.poi.hssf.model.FormulaParser;
+import org.apache.poi.hssf.record.formula.NumberPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.StringPtg;
+
+/**
+ *
+ * @author Josh Micich
+ */
+public class DVConstraint {
+ /**
+ * ValidationType enum
+ */
+ public static final class ValidationType {
+ private ValidationType() {
+ // no instances of this class
+ }
+ /** 'Any value' type - value not restricted */
+ public static final int ANY = 0x00;
+ /** Integer ('Whole number') type */
+ public static final int INTEGER = 0x01;
+ /** Decimal type */
+ public static final int DECIMAL = 0x02;
+ /** List type ( combo box type ) */
+ public static final int LIST = 0x03;
+ /** Date type */
+ public static final int DATE = 0x04;
+ /** Time type */
+ public static final int TIME = 0x05;
+ /** String length type */
+ public static final int TEXT_LENGTH = 0x06;
+ /** Formula ( 'Custom' ) type */
+ public static final int FORMULA = 0x07;
+ }
+ /**
+ * Condition operator enum
+ */
+ public static final class OperatorType {
+ private OperatorType() {
+ // no instances of this class
+ }
+
+ public static final int BETWEEN = 0x00;
+ public static final int NOT_BETWEEN = 0x01;
+ public static final int EQUAL = 0x02;
+ public static final int NOT_EQUAL = 0x03;
+ public static final int GREATER_THAN = 0x04;
+ public static final int LESS_THAN = 0x05;
+ public static final int GREATER_OR_EQUAL = 0x06;
+ public static final int LESS_OR_EQUAL = 0x07;
+ /** default value to supply when the operator type is not used */
+ public static final int IGNORED = BETWEEN;
+
+ /* package */ static void validateSecondArg(int comparisonOperator, String paramValue) {
+ switch (comparisonOperator) {
+ case BETWEEN:
+ case NOT_BETWEEN:
+ if (paramValue == null) {
+ throw new IllegalArgumentException("expr2 must be supplied for 'between' comparisons");
+ }
+ // all other operators don't need second arg
+ }
+ }
+ }
+
+ /* package */ static final class FormulaPair {
+
+ private final Ptg[] _formula1;
+ private final Ptg[] _formula2;
+
+ public FormulaPair(Ptg[] formula1, Ptg[] formula2) {
+ _formula1 = formula1;
+ _formula2 = formula2;
+ }
+ public Ptg[] getFormula1() {
+ return _formula1;
+ }
+ public Ptg[] getFormula2() {
+ return _formula2;
+ }
+
+ }
+
+ // convenient access to ValidationType namespace
+ private static final ValidationType VT = null;
+
+
+ private final int _validationType;
+ private int _operator;
+ private String[] _explicitListValues;
+
+ private String _formula1;
+ private String _formula2;
+ private Double _value1;
+ private Double _value2;
+
+
+ private DVConstraint(int validationType, int comparisonOperator, String formulaA,
+ String formulaB, Double value1, Double value2, String[] excplicitListValues) {
+ _validationType = validationType;
+ _operator = comparisonOperator;
+ _formula1 = formulaA;
+ _formula2 = formulaB;
+ _value1 = value1;
+ _value2 = value2;
+ _explicitListValues = excplicitListValues;
+ }
+
+
+ /**
+ * Creates a list constraint
+ */
+ private DVConstraint(String listFormula, String[] excplicitListValues) {
+ this(ValidationType.LIST, OperatorType.IGNORED,
+ listFormula, null, null, null, excplicitListValues);
+ }
+
+ /**
+ * Creates a number based data validation constraint. The text values entered for expr1 and expr2
+ * can be either standard Excel formulas or formatted number values. If the expression starts
+ * with '=' it is parsed as a formula, otherwise it is parsed as a formatted number.
+ *
+ * @param validationType one of {@link ValidationType#ANY}, {@link ValidationType#DECIMAL},
+ * {@link ValidationType#INTEGER}, {@link ValidationType#TEXT_LENGTH}
+ * @param comparisonOperator any constant from {@link OperatorType} enum
+ * @param expr1 date formula (when first char is '=') or formatted number value
+ * @param expr2 date formula (when first char is '=') or formatted number value
+ */
+ public static DVConstraint createNumericConstraint(int validationType, int comparisonOperator,
+ String expr1, String expr2) {
+ switch (validationType) {
+ case ValidationType.ANY:
+ if (expr1 != null || expr2 != null) {
+ throw new IllegalArgumentException("expr1 and expr2 must be null for validation type 'any'");
+ }
+ break;
+ case ValidationType.DECIMAL:
+ case ValidationType.INTEGER:
+ case ValidationType.TEXT_LENGTH:
+ if (expr1 == null) {
+ throw new IllegalArgumentException("expr1 must be supplied");
+ }
+ OperatorType.validateSecondArg(comparisonOperator, expr2);
+ break;
+ default:
+ throw new IllegalArgumentException("Validation Type ("
+ + validationType + ") not supported with this method");
+ }
+ // formula1 and value1 are mutually exclusive
+ String formula1 = getFormulaFromTextExpression(expr1);
+ Double value1 = formula1 == null ? convertNumber(expr1) : null;
+ // formula2 and value2 are mutually exclusive
+ String formula2 = getFormulaFromTextExpression(expr2);
+ Double value2 = formula2 == null ? convertNumber(expr2) : null;
+ return new DVConstraint(validationType, comparisonOperator, formula1, formula2, value1, value2, null);
+ }
+
+ public static DVConstraint createFormulaListConstraint(String listFormula) {
+ return new DVConstraint(listFormula, null);
+ }
+ public static DVConstraint createExplicitListConstraint(String[] explicitListValues) {
+ return new DVConstraint(null, explicitListValues);
+ }
+
+
+ /**
+ * Creates a time based data validation constraint. The text values entered for expr1 and expr2
+ * can be either standard Excel formulas or formatted time values. If the expression starts
+ * with '=' it is parsed as a formula, otherwise it is parsed as a formatted time. To parse
+ * formatted times, two formats are supported: "HH:MM" or "HH:MM:SS". This is contrary to
+ * Excel which uses the default time format from the OS.
+ *
+ * @param comparisonOperator constant from {@link OperatorType} enum
+ * @param expr1 date formula (when first char is '=') or formatted time value
+ * @param expr2 date formula (when first char is '=') or formatted time value
+ */
+ public static DVConstraint createTimeConstraint(int comparisonOperator, String expr1, String expr2) {
+ if (expr1 == null) {
+ throw new IllegalArgumentException("expr1 must be supplied");
+ }
+ OperatorType.validateSecondArg(comparisonOperator, expr1);
+
+ // formula1 and value1 are mutually exclusive
+ String formula1 = getFormulaFromTextExpression(expr1);
+ Double value1 = formula1 == null ? convertTime(expr1) : null;
+ // formula2 and value2 are mutually exclusive
+ String formula2 = getFormulaFromTextExpression(expr2);
+ Double value2 = formula2 == null ? convertTime(expr2) : null;
+ return new DVConstraint(VT.TIME, comparisonOperator, formula1, formula2, value1, value2, null);
+
+ }
+ /**
+ * Creates a date based data validation constraint. The text values entered for expr1 and expr2
+ * can be either standard Excel formulas or formatted date values. If the expression starts
+ * with '=' it is parsed as a formula, otherwise it is parsed as a formatted date (Excel uses
+ * the same convention). To parse formatted dates, a date format needs to be specified. This
+ * is contrary to Excel which uses the default short date format from the OS.
+ *
+ * @param comparisonOperator constant from {@link OperatorType} enum
+ * @param expr1 date formula (when first char is '=') or formatted date value
+ * @param expr2 date formula (when first char is '=') or formatted date value
+ * @param dateFormat ignored if both expr1 and expr2 are formulas. Default value is "YYYY/MM/DD"
+ * otherwise any other valid argument for <tt>SimpleDateFormat</tt> can be used
+ * @see <a href='http://java.sun.com/j2se/1.5.0/docs/api/java/text/DateFormat.html'>SimpleDateFormat</a>
+ */
+ public static DVConstraint createDateConstraint(int comparisonOperator, String expr1, String expr2, String dateFormat) {
+ if (expr1 == null) {
+ throw new IllegalArgumentException("expr1 must be supplied");
+ }
+ OperatorType.validateSecondArg(comparisonOperator, expr2);
+ SimpleDateFormat df = dateFormat == null ? null : new SimpleDateFormat(dateFormat);
+
+ // formula1 and value1 are mutually exclusive
+ String formula1 = getFormulaFromTextExpression(expr1);
+ Double value1 = formula1 == null ? convertDate(expr1, df) : null;
+ // formula2 and value2 are mutually exclusive
+ String formula2 = getFormulaFromTextExpression(expr2);
+ Double value2 = formula2 == null ? convertDate(expr2, df) : null;
+ return new DVConstraint(VT.DATE, comparisonOperator, formula1, formula2, value1, value2, null);
+ }
+
+ /**
+ * Distinguishes formula expressions from simple value expressions. This logic is only
+ * required by a few factory methods in this class that create data validation constraints
+ * from more or less the same parameters that would have been entered in the Excel UI. The
+ * data validation dialog box uses the convention that formulas begin with '='. Other methods
+ * in this class follow the POI convention (formulas and values are distinct), so the '='
+ * convention is not used there.
+ *
+ * @param textExpr a formula or value expression
+ * @return all text after '=' if textExpr begins with '='. Otherwise <code>null</code> if textExpr does not begin with '='
+ */
+ private static String getFormulaFromTextExpression(String textExpr) {
+ if (textExpr == null) {
+ return null;
+ }
+ if (textExpr.length() < 1) {
+ throw new IllegalArgumentException("Empty string is not a valid formula/value expression");
+ }
+ if (textExpr.charAt(0) == '=') {
+ return textExpr.substring(1);
+ }
+ return null;
+ }
+
+
+ /**
+ * @return <code>null</code> if numberStr is <code>null</code>
+ */
+ private static Double convertNumber(String numberStr) {
+ if (numberStr == null) {
+ return null;
+ }
+ try {
+ return new Double(numberStr);
+ } catch (NumberFormatException e) {
+ throw new RuntimeException("The supplied text '" + numberStr
+ + "' could not be parsed as a number");
+ }
+ }
+
+ /**
+ * @return <code>null</code> if timeStr is <code>null</code>
+ */
+ private static Double convertTime(String timeStr) {
+ if (timeStr == null) {
+ return null;
+ }
+ return new Double(HSSFDateUtil.convertTime(timeStr));
+ }
+ /**
+ * @param dateFormat pass <code>null</code> for default YYYYMMDD
+ * @return <code>null</code> if timeStr is <code>null</code>
+ */
+ private static Double convertDate(String dateStr, SimpleDateFormat dateFormat) {
+ if (dateStr == null) {
+ return null;
+ }
+ Date dateVal;
+ if (dateFormat == null) {
+ dateVal = HSSFDateUtil.parseYYYYMMDDDate(dateStr);
+ } else {
+ try {
+ dateVal = dateFormat.parse(dateStr);
+ } catch (ParseException e) {
+ throw new RuntimeException("Failed to parse date '" + dateStr
+ + "' using specified format '" + dateFormat + "'", e);
+ }
+ }
+ return new Double(HSSFDateUtil.getExcelDate(dateVal));
+ }
+
+ public static DVConstraint createFormulaConstraint(String formula) {
+ if (formula == null) {
+ throw new IllegalArgumentException("formula must be supplied");
+ }
+ return new DVConstraint(VT.FORMULA, OperatorType.IGNORED, formula, null, null, null, null);
+ }
+
+ /**
+ * @return both parsed formulas (for expression 1 and 2).
+ */
+ /* package */ FormulaPair createFormulas(HSSFWorkbook workbook) {
+ Ptg[] formula1;
+ Ptg[] formula2;
+ if (isListValidationType()) {
+ formula1 = createListFormula(workbook);
+ formula2 = Ptg.EMPTY_PTG_ARRAY;
+ } else {
+ formula1 = convertDoubleFormula(_formula1, _value1, workbook);
+ formula2 = convertDoubleFormula(_formula2, _value2, workbook);
+ }
+ return new FormulaPair(formula1, formula2);
+ }
+
+ private Ptg[] createListFormula(HSSFWorkbook workbook) {
+
+ if (_explicitListValues == null) {
+ // formula is parsed with slightly different RVA rules: (root node type must be 'reference')
+ return FormulaParser.parse(_formula1, workbook, FormulaParser.FORMULA_TYPE_DATAVALIDATION_LIST);
+ // To do: Excel places restrictions on the available operations within a list formula.
+ // Some things like union and intersection are not allowed.
+ }
+ // explicit list was provided
+ StringBuffer sb = new StringBuffer(_explicitListValues.length * 16);
+ for (int i = 0; i < _explicitListValues.length; i++) {
+ if (i > 0) {
+ sb.append('\0'); // list delimiter is the nul char
+ }
+ sb.append(_explicitListValues[i]);
+
+ }
+ return new Ptg[] { new StringPtg(sb.toString()), };
+ }
+
+ /**
+ * @return The parsed token array representing the formula or value specified.
+ * Empty array if both formula and value are <code>null</code>
+ */
+ private static Ptg[] convertDoubleFormula(String formula, Double value, HSSFWorkbook workbook) {
+ if (formula == null) {
+ if (value == null) {
+ return Ptg.EMPTY_PTG_ARRAY;
+ }
+ return new Ptg[] { new NumberPtg(value.doubleValue()), };
+ }
+ if (value != null) {
+ throw new IllegalStateException("Both formula and value cannot be present");
+ }
+ return FormulaParser.parse(formula, workbook);
+ }
+
+
+ /**
+ * @return data validation type of this constraint
+ * @see ValidationType
+ */
+ public int getValidationType() {
+ return _validationType;
+ }
+ /**
+ * Convenience method
+ * @return <code>true</code> if this constraint is a 'list' validation
+ */
+ public boolean isListValidationType() {
+ return _validationType == VT.LIST;
+ }
+ /**
+ * Convenience method
+ * @return <code>true</code> if this constraint is a 'list' validation with explicit values
+ */
+ public boolean isExplicitList() {
+ return _validationType == VT.LIST && _explicitListValues != null;
+ }
+ /**
+ * @return the operator used for this constraint
+ * @see OperatorType
+ */
+ public int getOperator() {
+ return _operator;
+ }
+ /**
+ * Sets the comparison operator for this constraint
+ * @see OperatorType
+ */
+ public void setOperator(int operator) {
+ _operator = operator;
+ }
+
+ public String[] getExplicitListValues() {
+ return _explicitListValues;
+ }
+ public void setExplicitListValues(String[] explicitListValues) {
+ if (_validationType != VT.LIST) {
+ throw new RuntimeException("Cannot setExplicitListValues on non-list constraint");
+ }
+ _formula1 = null;
+ _explicitListValues = explicitListValues;
+ }
+
+ /**
+ * @return the formula for expression 1. May be <code>null</code>
+ */
+ public String getFormula1() {
+ return _formula1;
+ }
+ /**
+ * Sets a formula for expression 1.
+ */
+ public void setFormula1(String formula1) {
+ _value1 = null;
+ _explicitListValues = null;
+ _formula1 = formula1;
+ }
+
+ /**
+ * @return the formula for expression 2. May be <code>null</code>
+ */
+ public String getFormula2() {
+ return _formula2;
+ }
+ /**
+ * Sets a formula for expression 2.
+ */
+ public void setFormula2(String formula2) {
+ _value2 = null;
+ _formula2 = formula2;
+ }
+
+ /**
+ * @return the numeric value for expression 1. May be <code>null</code>
+ */
+ public Double getValue1() {
+ return _value1;
+ }
+ /**
+ * Sets a numeric value for expression 1.
+ */
+ public void setValue1(double value1) {
+ _formula1 = null;
+ _value1 = new Double(value1);
+ }
+
+ /**
+ * @return the numeric value for expression 2. May be <code>null</code>
+ */
+ public Double getValue2() {
+ return _value2;
+ }
+ /**
+ * Sets a numeric value for expression 2.
+ */
+ public void setValue2(double value2) {
+ _formula2 = null;
+ _value2 = new Double(value2);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.usermodel;
+
+import org.apache.poi.hssf.record.DVRecord;
+import org.apache.poi.hssf.usermodel.DVConstraint.FormulaPair;
+import org.apache.poi.hssf.util.CellRangeAddressList;
+
+/**
+ *Utility class for creating data validation cells
+ *
+ * @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
+ */
+public final class HSSFDataValidation {
+ /**
+ * Error style constants for error box
+ */
+ public static final class ErrorStyle {
+ /** STOP style */
+ public static final int STOP = 0x00;
+ /** WARNING style */
+ public static final int WARNING = 0x01;
+ /** INFO style */
+ public static final int INFO = 0x02;
+ }
+
+ private String _prompt_title;
+ private String _prompt_text;
+ private String _error_title;
+ private String _error_text;
+
+ private int _errorStyle = ErrorStyle.STOP;
+ private boolean _emptyCellAllowed = true;
+ private boolean _suppress_dropdown_arrow = false;
+ private boolean _showPromptBox = true;
+ private boolean _showErrorBox = true;
+ private final CellRangeAddressList _regions;
+ private DVConstraint _constraint;
+
+ /**
+ * Constructor which initializes the cell range on which this object will be
+ * applied
+ * @param constraint
+ */
+ public HSSFDataValidation(CellRangeAddressList regions, DVConstraint constraint) {
+ _regions = regions;
+ _constraint = constraint;
+ }
+
+
+ public DVConstraint getConstraint() {
+ return _constraint;
+ }
+
+ /**
+ * Sets the error style for error box
+ * @see ErrorStyle
+ */
+ public void setErrorStyle(int error_style) {
+ _errorStyle = error_style;
+ }
+
+ /**
+ * @return the error style of error box
+ * @see ErrorStyle
+ */
+ public int getErrorStyle() {
+ return _errorStyle;
+ }
+
+ /**
+ * Sets if this object allows empty as a valid value
+ *
+ * @param allowed <code>true</code> if this object should treats empty as valid value , <code>false</code>
+ * otherwise
+ */
+ public void setEmptyCellAllowed(boolean allowed) {
+ _emptyCellAllowed = 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 _emptyCellAllowed;
+ }
+
+ /**
+ * Useful for list validation objects .
+ *
+ * @param suppress
+ * 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 setSuppressDropDownArrow(boolean suppress) {
+ _suppress_dropdown_arrow = suppress;
+ }
+
+ /**
+ * Useful only list validation objects . This method always returns false if
+ * the object isn't a list validation object
+ *
+ * @return <code>true</code> if a list should display the values into a drop down list ,
+ * <code>false</code> otherwise .
+ */
+ public boolean getSuppressDropDownArrow() {
+ if (_constraint.isListValidationType()) {
+ return _suppress_dropdown_arrow;
+ }
+ return false;
+ }
+
+ /**
+ * Sets the behaviour when a cell which belongs to this object is selected
+ *
+ * @param show <code>true</code> if an prompt box should be displayed , <code>false</code> otherwise
+ */
+ public void setShowPromptBox(boolean show) {
+ _showPromptBox = show;
+ }
+
+ /**
+ * @param show <code>true</code> if an prompt box should be displayed , <code>false</code> otherwise
+ */
+ public boolean getShowPromptBox() {
+ return _showPromptBox;
+ }
+
+ /**
+ * Sets the behaviour when an invalid value is entered
+ *
+ * @param show <code>true</code> if an error box should be displayed , <code>false</code> otherwise
+ */
+ public void setShowErrorBox(boolean show) {
+ _showErrorBox = show;
+ }
+
+ /**
+ * @return <code>true</code> if an error box should be displayed , <code>false</code> otherwise
+ */
+ public boolean getShowErrorBox() {
+ return _showErrorBox;
+ }
+
+
+ /**
+ * 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
+ */
+ public void createPromptBox(String title, String text) {
+ _prompt_title = title;
+ _prompt_text = text;
+ this.setShowPromptBox(true);
+ }
+
+ /**
+ * @return Prompt box's title or <code>null</code>
+ */
+ public String getPromptBoxTitle() {
+ return _prompt_title;
+ }
+
+ /**
+ * @return Prompt box's text or <code>null</code>
+ */
+ public String getPromptBoxText() {
+ return _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
+ */
+ public void createErrorBox(String title, String text) {
+ _error_title = title;
+ _error_text = text;
+ this.setShowErrorBox(true);
+ }
+
+ /**
+ * @return Error box's title or <code>null</code>
+ */
+ public String getErrorBoxTitle() {
+ return _error_title;
+ }
+
+ /**
+ * @return Error box's text or <code>null</code>
+ */
+ public String getErrorBoxText() {
+ return _error_text;
+ }
+
+ public DVRecord createDVRecord(HSSFWorkbook workbook) {
+
+ FormulaPair fp = _constraint.createFormulas(workbook);
+
+ return new DVRecord(_constraint.getValidationType(),
+ _constraint.getOperator(),
+ _errorStyle, _emptyCellAllowed, getSuppressDropDownArrow(),
+ _constraint.isExplicitList(),
+ _showPromptBox, _prompt_title, _prompt_text,
+ _showErrorBox, _error_title, _error_text,
+ fp.getFormula1(), fp.getFormula2(),
+ _regions);
+ }
+}
\ No newline at end of file
==================================================================== */
-
-/*
- * DateUtil.java
- *
- * Created on January 19, 2002, 9:30 AM
- */
package org.apache.poi.hssf.usermodel;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.regex.Pattern;
/**
* Contains methods for dealing with Excel dates.
* @author Alex Jacoby (ajacoby at gmail.com)
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
*/
-
-public class HSSFDateUtil
-{
- private HSSFDateUtil()
- {
+public final class HSSFDateUtil {
+ private HSSFDateUtil() {
+ // no instances of this class
}
+ private static final int SECONDS_PER_MINUTE = 60;
+ private static final int MINUTES_PER_HOUR = 60;
+ private static final int HOURS_PER_DAY = 24;
+ private static final int SECONDS_PER_DAY = (HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
+
+ private static final int BAD_DATE = -1; // used to specify that date is invalid
+ private static final long DAY_MILLISECONDS = SECONDS_PER_DAY * 1000L;
+
+ private static final Pattern TIME_SEPARATOR_PATTERN = Pattern.compile(":");
- private static final int BAD_DATE =
- -1; // used to specify that date is invalid
- private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
-
/**
* 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.
* @param date the Date
*/
public static double getExcelDate(Date date) {
- return getExcelDate(date, false);
+ return getExcelDate(date, false);
}
/**
* Given a Date, converts it into a double representing its internal Excel representation,
}
/**
* Given a Date in the form of a Calendar, converts it into a double
- * representing its internal Excel representation, which is the
- * number of days since 1/1/1900. Fractional days represent hours,
+ * 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 use1904windowing Should 1900 or 1904 date windowing be used?
*/
public static double getExcelDate(Calendar date, boolean use1904windowing) {
- // Don't alter the supplied Calendar as we do our work
- return internalGetExcelDate( (Calendar)date.clone(), use1904windowing );
+ // Don't alter the supplied Calendar as we do our work
+ return internalGetExcelDate( (Calendar)date.clone(), use1904windowing );
}
private static double internalGetExcelDate(Calendar date, boolean use1904windowing) {
- if ((!use1904windowing && date.get(Calendar.YEAR) < 1900) ||
- (use1904windowing && date.get(Calendar.YEAR) < 1904))
+ if ((!use1904windowing && date.get(Calendar.YEAR) < 1900) ||
+ (use1904windowing && date.get(Calendar.YEAR) < 1904))
{
return BAD_DATE;
- } else {
- // Because of daylight time saving we cannot use
- // date.getTime() - calStart.getTimeInMillis()
- // as the difference in milliseconds between 00:00 and 04:00
- // can be 3, 4 or 5 hours but Excel expects it to always
- // be 4 hours.
- // E.g. 2004-03-28 04:00 CEST - 2004-03-28 00:00 CET is 3 hours
- // and 2004-10-31 04:00 CET - 2004-10-31 00:00 CEST is 5 hours
- double fraction = (((date.get(Calendar.HOUR_OF_DAY) * 60
- + date.get(Calendar.MINUTE)
- ) * 60 + date.get(Calendar.SECOND)
- ) * 1000 + date.get(Calendar.MILLISECOND)
- ) / ( double ) DAY_MILLISECONDS;
- Calendar calStart = dayStart(date);
-
- double value = fraction + absoluteDay(calStart, use1904windowing);
-
- if (!use1904windowing && value >= 60) {
- value++;
- } else if (use1904windowing) {
- value--;
- }
-
- return value;
}
+ // Because of daylight time saving we cannot use
+ // date.getTime() - calStart.getTimeInMillis()
+ // as the difference in milliseconds between 00:00 and 04:00
+ // can be 3, 4 or 5 hours but Excel expects it to always
+ // be 4 hours.
+ // E.g. 2004-03-28 04:00 CEST - 2004-03-28 00:00 CET is 3 hours
+ // and 2004-10-31 04:00 CET - 2004-10-31 00:00 CEST is 5 hours
+ double fraction = (((date.get(Calendar.HOUR_OF_DAY) * 60
+ + date.get(Calendar.MINUTE)
+ ) * 60 + date.get(Calendar.SECOND)
+ ) * 1000 + date.get(Calendar.MILLISECOND)
+ ) / ( double ) DAY_MILLISECONDS;
+ Calendar calStart = dayStart(date);
+
+ double value = fraction + absoluteDay(calStart, use1904windowing);
+
+ if (!use1904windowing && value >= 60) {
+ value++;
+ } else if (use1904windowing) {
+ value--;
+ }
+
+ return value;
}
-
+
/**
* Given an Excel date with using 1900 date windowing, and
* converts it to a java.util.Date.
* <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);
+ return getJavaDate(date, false);
}
/**
* Given an Excel date with either 1900 or 1904 date windowing,
* @see java.util.TimeZone
*/
public static Date getJavaDate(double date, boolean use1904windowing) {
- if (isValidExcelDate(date)) {
- int startYear = 1900;
- int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
- int wholeDays = (int)Math.floor(date);
- if (use1904windowing) {
- startYear = 1904;
- dayAdjust = 1; // 1904 date windowing uses 1/2/1904 as the first day
- }
- else if (wholeDays < 61) {
- // Date is prior to 3/1/1900, so adjust because Excel thinks 2/29/1900 exists
- // If Excel date == 2/29/1900, will become 3/1/1900 in Java representation
- dayAdjust = 0;
- }
- GregorianCalendar calendar = new GregorianCalendar(startYear,0,
- wholeDays + dayAdjust);
- int millisecondsInDay = (int)((date - Math.floor(date)) *
- DAY_MILLISECONDS + 0.5);
- calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
- return calendar.getTime();
- }
- else {
+ if (!isValidExcelDate(date)) {
return null;
}
+ int startYear = 1900;
+ int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
+ int wholeDays = (int)Math.floor(date);
+ if (use1904windowing) {
+ startYear = 1904;
+ dayAdjust = 1; // 1904 date windowing uses 1/2/1904 as the first day
+ }
+ else if (wholeDays < 61) {
+ // Date is prior to 3/1/1900, so adjust because Excel thinks 2/29/1900 exists
+ // If Excel date == 2/29/1900, will become 3/1/1900 in Java representation
+ dayAdjust = 0;
+ }
+ GregorianCalendar calendar = new GregorianCalendar(startYear,0,
+ wholeDays + dayAdjust);
+ int millisecondsInDay = (int)((date - Math.floor(date)) *
+ DAY_MILLISECONDS + 0.5);
+ calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
+ return calendar.getTime();
}
-
+
/**
* Given a format ID and its format String, will check to see if the
* format represents a date format or not.
* Firstly, it will check to see if the format ID corresponds to an
- * internal excel date format (eg most US date formats)
+ * internal excel date format (eg most US date formats)
* If not, it will check to see if the format string only contains
* date formatting characters (ymd-/), which covers most
* non US date formats.
- *
+ *
* @param formatIndex The index of the format, eg from ExtendedFormatRecord.getFormatIndex
* @param formatString The format string, eg from FormatRecord.getFormatString
* @see #isInternalDateFormat(int)
*/
public static boolean isADateFormat(int formatIndex, String formatString) {
- // First up, is this an internal date format?
- if(isInternalDateFormat(formatIndex)) {
- return true;
- }
-
- // If we didn't get a real string, it can't be
- if(formatString == null || formatString.length() == 0) {
- return false;
- }
-
- String fs = formatString;
-
- // Translate \- into just -, before matching
- fs = fs.replaceAll("\\\\-","-");
- // And \, into ,
- fs = fs.replaceAll("\\\\,",",");
- // And '\ ' into ' '
- fs = fs.replaceAll("\\\\ "," ");
-
- // If it end in ;@, that's some crazy dd/mm vs mm/dd
- // switching stuff, which we can ignore
- fs = fs.replaceAll(";@", "");
-
- // If it starts with [$-...], then could be a date, but
- // who knows what that starting bit is all about
- fs = fs.replaceAll("^\\[\\$\\-.*?\\]", "");
-
- // If it starts with something like [Black] or [Yellow],
- // then it could be a date
- fs = fs.replaceAll("^\\[[a-zA-Z]+\\]", "");
-
- // Otherwise, check it's only made up, in any case, of:
- // y m d h s - / , . :
- // optionally followed by AM/PM
- if(fs.matches("^[yYmMdDhHsS\\-/,. :]+[ampAMP/]*$")) {
- return true;
- }
-
- return false;
+ // First up, is this an internal date format?
+ if(isInternalDateFormat(formatIndex)) {
+ return true;
+ }
+
+ // If we didn't get a real string, it can't be
+ if(formatString == null || formatString.length() == 0) {
+ return false;
+ }
+
+ String fs = formatString;
+
+ // Translate \- into just -, before matching
+ fs = fs.replaceAll("\\\\-","-");
+ // And \, into ,
+ fs = fs.replaceAll("\\\\,",",");
+ // And '\ ' into ' '
+ fs = fs.replaceAll("\\\\ "," ");
+
+ // If it end in ;@, that's some crazy dd/mm vs mm/dd
+ // switching stuff, which we can ignore
+ fs = fs.replaceAll(";@", "");
+
+ // If it starts with [$-...], then could be a date, but
+ // who knows what that starting bit is all about
+ fs = fs.replaceAll("^\\[\\$\\-.*?\\]", "");
+
+ // If it starts with something like [Black] or [Yellow],
+ // then it could be a date
+ fs = fs.replaceAll("^\\[[a-zA-Z]+\\]", "");
+
+ // Otherwise, check it's only made up, in any case, of:
+ // y m d h s - / , . :
+ // optionally followed by AM/PM
+ if(fs.matches("^[yYmMdDhHsS\\-/,. :]+[ampAMP/]*$")) {
+ return true;
+ }
+
+ return false;
}
/**
* Given a format ID this will check whether the format represents
* an internal excel date format or not.
- * @see #isADateFormat(int, java.lang.String)
+ * @see #isADateFormat(int, java.lang.String)
*/
public static boolean isInternalDateFormat(int format) {
- boolean retval =false;
-
switch(format) {
// Internal Date Formats as described on page 427 in
// Microsoft Excel Dev's Kit...
case 0x2d:
case 0x2e:
case 0x2f:
- retval = true;
- break;
-
- default:
- retval = false;
- break;
+ return true;
}
- return retval;
+ return false;
}
/**
* 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.
+ * 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 #isInternalDateFormat(int)
*/
public static boolean isCellDateFormatted(HSSFCell cell) {
if (cell == null) return false;
boolean bDate = false;
-
+
double d = cell.getNumericCellValue();
if ( HSSFDateUtil.isValidExcelDate(d) ) {
HSSFCellStyle style = cell.getCellStyle();
public static boolean isCellInternalDateFormatted(HSSFCell cell) {
if (cell == null) return false;
boolean bDate = false;
-
+
double d = cell.getNumericCellValue();
if ( HSSFDateUtil.isValidExcelDate(d) ) {
HSSFCellStyle style = cell.getCellStyle();
*
* @return days number of days in years prior to yr.
* @param yr a year (1900 < yr < 4000)
- * @param use1904windowing
+ * @param use1904windowing
* @exception IllegalArgumentException if year is outside of range.
*/
if ((!use1904windowing && yr < 1900) || (use1904windowing && yr < 1900)) {
throw new IllegalArgumentException("'year' must be 1900 or greater");
}
-
+
int yr1 = yr - 1;
int leapDays = yr1 / 4 // plus julian leap days in prior years
- yr1 / 100 // minus prior century years
- + yr1 / 400 // plus years divisible by 400
+ + yr1 / 400 // plus years divisible by 400
- 460; // leap days in previous 1900 years
-
+
return 365 * (yr - (use1904windowing ? 1904 : 1900)) + leapDays;
}
-
+
// set HH:MM:SS fields of cal to 00:00:00:000
private static Calendar dayStart(final Calendar cal)
{
return cal;
}
- // ---------------------------------------------------------------------------------------------------------
+
+ private static final class FormatException extends Exception {
+ public FormatException(String msg) {
+ super(msg);
+ }
+ }
+
+ /**
+ * Converts a string of format "HH:MM" or "HH:MM:SS" to its (Excel) numeric equivalent
+ *
+ * @return a double between 0 and 1 representing the fraction of the day
+ */
+ public static double convertTime(String timeStr) {
+ try {
+ return convertTimeInternal(timeStr);
+ } catch (FormatException e) {
+ String msg = "Bad time format '" + timeStr
+ + "' expected 'HH:MM' or 'HH:MM:SS' - " + e.getMessage();
+ throw new IllegalArgumentException(msg);
+ }
+ }
+ private static double convertTimeInternal(String timeStr) throws FormatException {
+ int len = timeStr.length();
+ if (len < 4 || len > 8) {
+ throw new FormatException("Bad length");
+ }
+ String[] parts = TIME_SEPARATOR_PATTERN.split(timeStr);
+
+ String secStr;
+ switch (parts.length) {
+ case 2: secStr = "00"; break;
+ case 3: secStr = parts[2]; break;
+ default:
+ throw new FormatException("Expected 2 or 3 fields but got (" + parts.length + ")");
+ }
+ String hourStr = parts[0];
+ String minStr = parts[1];
+ int hours = parseInt(hourStr, "hour", HOURS_PER_DAY);
+ int minutes = parseInt(minStr, "minute", MINUTES_PER_HOUR);
+ int seconds = parseInt(secStr, "second", SECONDS_PER_MINUTE);
+
+ double totalSeconds = seconds + (minutes + (hours) * 60) * 60;
+ return totalSeconds / (SECONDS_PER_DAY);
+ }
+ /**
+ * Converts a string of format "YYYY/MM/DD" to its (Excel) numeric equivalent
+ *
+ * @return a double representing the (integer) number of days since the start of the Excel epoch
+ */
+ public static Date parseYYYYMMDDDate(String dateStr) {
+ try {
+ return parseYYYYMMDDDateInternal(dateStr);
+ } catch (FormatException e) {
+ String msg = "Bad time format " + dateStr
+ + " expected 'YYYY/MM/DD' - " + e.getMessage();
+ throw new IllegalArgumentException(msg);
+ }
+ }
+ private static Date parseYYYYMMDDDateInternal(String timeStr) throws FormatException {
+ if(timeStr.length() != 10) {
+ throw new FormatException("Bad length");
+ }
+
+ String yearStr = timeStr.substring(0, 4);
+ String monthStr = timeStr.substring(5, 7);
+ String dayStr = timeStr.substring(8, 10);
+ int year = parseInt(yearStr, "year", Short.MIN_VALUE, Short.MAX_VALUE);
+ int month = parseInt(monthStr, "month", 1, 12);
+ int day = parseInt(dayStr, "day", 1, 31);
+
+ Calendar cal = new GregorianCalendar(year, month-1, day, 0, 0, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ return cal.getTime();
+ }
+ private static int parseInt(String strVal, String fieldName, int rangeMax) throws FormatException {
+ return parseInt(strVal, fieldName, 0, rangeMax-1);
+ }
+
+ private static int parseInt(String strVal, String fieldName, int lowerLimit, int upperLimit) throws FormatException {
+ int result;
+ try {
+ result = Integer.parseInt(strVal);
+ } catch (NumberFormatException e) {
+ throw new FormatException("Bad int format '" + strVal + "' for " + fieldName + " field");
+ }
+ if (result < lowerLimit || result > upperLimit) {
+ throw new FormatException(fieldName + " value (" + result
+ + ") is outside the allowable range(0.." + upperLimit + ")");
+ }
+ return result;
+ }
}
import org.apache.poi.hssf.record.aggregates.DataValidityTable;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.RefPtg;
-import org.apache.poi.hssf.util.HSSFDataValidation;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.POILogFactory;
}
DataValidityTable dvt = sheet.getOrCreateDataValidityTable();
- dvt.addDataValidation(dataValidation, workbook);
+ DVRecord dvRecord = dataValidation.createDVRecord(workbook);
+ dvt.addDataValidation(dvRecord);
}
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hssf.util;\r
+\r
+import org.apache.poi.hssf.record.RecordInputStream;\r
+import org.apache.poi.util.LittleEndian;\r
+\r
+/**\r
+ * See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'\r
+ * \r
+ * @author Dragos Buleandra (dragos.buleandra@trade2b.ro)\r
+ */\r
+public final class CellRangeAddress {\r
+ private static final int ENCODED_SIZE = 8;\r
+\r
+ private int _firstRow;\r
+ private int _firstCol;\r
+ private int _lastRow;\r
+ private int _lastCol;\r
+\r
+ /*\r
+ * TODO - replace other incarnations of 'Cell Range Address' throughout POI:\r
+ * org.apache.poi.hssf.util.CellRange\r
+ * org.apache.poi.hssf.record.cf.CellRange\r
+ * org.apache.poi.hssf.util.HSSFCellRangeAddress.AddrStructure\r
+ * org.apache.poi.hssf.record.MergeCellsRecord.MergedRegion\r
+ * org.apache.poi.hssf.record.SelectionRecord.Reference\r
+ * \r
+ */\r
+ \r
+ public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {\r
+ _firstRow = firstRow;\r
+ _lastRow = lastRow;\r
+ _firstCol = firstCol;\r
+ _lastCol = lastCol;\r
+ }\r
+\r
+ public CellRangeAddress(RecordInputStream in) {\r
+ if (in.remaining() < ENCODED_SIZE) {\r
+ // Ran out of data\r
+ throw new RuntimeException("Ran out of data reading CellRangeAddress");\r
+ } \r
+ _firstRow = in.readUShort();\r
+ _lastRow = in.readUShort();\r
+ _firstCol = in.readUShort();\r
+ _lastCol = in.readUShort();\r
+ }\r
+\r
+ /**\r
+ * @return column number for the upper left hand corner\r
+ */\r
+ public int getFirstColumn() {\r
+ return _firstCol;\r
+ }\r
+\r
+ /**\r
+ * @return row number for the upper left hand corner\r
+ */\r
+ public int getFirstRow() {\r
+ return _firstRow;\r
+ }\r
+\r
+ /**\r
+ * @return column number for the lower right hand corner\r
+ */\r
+ public int getLastColumn() {\r
+ return _lastCol;\r
+ }\r
+\r
+ /**\r
+ * @return row number for the lower right hand corner\r
+ */\r
+ public int getLastRow() {\r
+ return _lastRow;\r
+ }\r
+\r
+ /**\r
+ * @param _firstCol column number for the upper left hand corner\r
+ */\r
+ public void setFirstColumn(int firstCol) {\r
+ _firstCol = firstCol;\r
+ }\r
+\r
+ /**\r
+ * @param rowFrom row number for the upper left hand corner\r
+ */\r
+ public void setFirstRow(int firstRow) {\r
+ _firstRow = firstRow;\r
+ }\r
+\r
+ /**\r
+ * @param colTo column number for the lower right hand corner\r
+ */\r
+ public void setLastColumn(int lastCol) {\r
+ _lastCol = lastCol;\r
+ }\r
+\r
+ /**\r
+ * @param rowTo row number for the lower right hand corner\r
+ */\r
+ public void setLastRow(int lastRow) {\r
+ _lastRow = lastRow;\r
+ }\r
+\r
+ /* package */ int serialize(byte[] data, int offset) {\r
+ LittleEndian.putUShort(data, offset + 0, _firstRow);\r
+ LittleEndian.putUShort(data, offset + 2, _lastRow);\r
+ LittleEndian.putUShort(data, offset + 4, _firstCol);\r
+ LittleEndian.putUShort(data, offset + 6, _lastCol);\r
+ return ENCODED_SIZE;\r
+ }\r
+\r
+ public static int getEncodedSize(int numberOfItems) {\r
+ return numberOfItems * ENCODED_SIZE;\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * Implementation of the cell range address lists,like is described
+ * in OpenOffice.org's Excel Documentation: excelfileformat.pdf sec 2.5.14 -
+ * 'Cell Range Address List'
+ *
+ * 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>
+ *
+ * @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
+ */
+public final class CellRangeAddressList {
+
+ /**
+ * List of <tt>CellRangeAddress</tt>es. Each structure represents a cell range
+ */
+ private final List _list;
+
+ public CellRangeAddressList() {
+ _list = new ArrayList();
+ }
+ /**
+ * Convenience constructor for creating a <tt>CellRangeAddressList</tt> with a single
+ * <tt>CellRangeAddress</tt>. Other <tt>CellRangeAddress</tt>es may be added later.
+ */
+ public CellRangeAddressList(int firstRow, int lastRow, int firstCol, int lastCol) {
+ this();
+ addCellRangeAddress(firstRow, firstCol, lastRow, lastCol);
+ }
+
+ /**
+ * @param in the RecordInputstream to read the record from
+ */
+ public CellRangeAddressList(RecordInputStream in) {
+ int nItems = in.readUShort();
+ _list = new ArrayList(nItems);
+
+ for (int k = 0; k < nItems; k++) {
+ _list.add(new CellRangeAddress(in));
+ }
+ }
+
+ /**
+ * 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 int getADDRStructureNumber() {
+ return _list.size();
+ }
+
+ /**
+ * Add an ADDR structure .
+ *
+ * @param firstRow - the upper left hand corner's row
+ * @param firstCol - the upper left hand corner's col
+ * @param lastRow - the lower right hand corner's row
+ * @param lastCol - the lower right hand corner's col
+ * @return the index of this ADDR structure
+ */
+ public void addCellRangeAddress(int firstRow, int firstCol, int lastRow, int lastCol) {
+ CellRangeAddress region = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
+ _list.add(region);
+ }
+
+ /**
+ * @return <tt>CellRangeAddress</tt> at the given index
+ */
+ public CellRangeAddress getCellRangeAddress(int index) {
+ return (CellRangeAddress) _list.get(index);
+ }
+
+ public int serialize(int offset, byte[] data) {
+ int pos = 2;
+
+ int nItems = _list.size();
+ LittleEndian.putUShort(data, offset, nItems);
+ for (int k = 0; k < nItems; k++) {
+ CellRangeAddress region = (CellRangeAddress) _list.get(k);
+ pos += region.serialize(data, offset + pos);
+ }
+ return getSize();
+ }
+
+ public int getSize() {
+ return 2 + CellRangeAddress.getEncodedSize(_list.size());
+ }
+}
+++ /dev/null
-/* ====================================================================
- 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 org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-
-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
-{
- private static POILogger logger = POILogFactory.getLogger(HSSFCellRangeAddress.class);
-
- /**
- * 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 = first_row;
- short last_col = first_col;
- if(in.remaining() >= 4) {
- last_row = in.readShort();
- last_col = in.readShort();
- } else {
- // Ran out of data
- // For now, issue a warning, finish, and
- // hope for the best....
- logger.log(POILogger.WARN, "Ran out of data reading cell references for DVRecord");
- k = this.field_addr_number;
- }
-
- 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;
- }
- }
-}
-
-
+++ /dev/null
-/* ====================================================================
- 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 ;
- }
- /**
- * @deprecated - (Jul-2008) use setSuppressDropDownArrow
- */
- public void setSurppressDropDownArrow( boolean suppress ) {
- setSuppressDropDownArrow(suppress);
- }
- /**
- * @deprecated - (Jul-2008) use getSuppressDropDownArrow
- */
- public boolean getSurppressDropDownArrow( ) {
- return getSuppressDropDownArrow();
- }
-
- /**
- * 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 setSuppressDropDownArrow( 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 getSuppressDropDownArrow( )
- {
- 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
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.text.SimpleDateFormat;
+import java.io.InputStream;
+import java.io.PrintStream;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.eventmodel.EventRecordFactory;
import org.apache.poi.hssf.record.DVRecord;
import org.apache.poi.hssf.record.RecordFormatException;
+import org.apache.poi.hssf.util.CellRangeAddressList;
import org.apache.poi.hssf.util.HSSFColor;
-import org.apache.poi.hssf.util.HSSFDataValidation;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
/**
- * <p>Title: TestDataValidation</p>
- * <p>Description: Class for testing Excel's data validation mechanism
- * Second test :
- * -
- * </p>
+ * Class for testing Excel's data validation mechanism
+ *
* @author Dragos Buleandra ( dragos.buleandra@trade2b.ro )
*/
-public class TestDataValidation extends TestCase
-{
-
- public void testDataValidation() throws Exception
- {
- System.out.println("\nTest no. 2 - Test Excel's Data validation mechanism");
- String resultFile = System.getProperty("java.io.tmpdir")+File.separator+"TestDataValidation.xls";
- HSSFWorkbook wb = new HSSFWorkbook();
-
- HSSFCellStyle style_1 = this.createStyle( wb, HSSFCellStyle.ALIGN_LEFT );
- HSSFCellStyle style_2 = this.createStyle( wb, HSSFCellStyle.ALIGN_CENTER );
- HSSFCellStyle style_3 = this.createStyle( wb, HSSFCellStyle.ALIGN_CENTER, HSSFColor.GREY_25_PERCENT.index, true );
- HSSFCellStyle style_4 = this.createHeaderStyle(wb);
- HSSFDataValidation data_validation = null;
-
- //data validation's number types
- System.out.print(" Create sheet for Data Validation's number types ... ");
- HSSFSheet fSheet = wb.createSheet("Number types");
-
- //"Whole number" validation type
- this.createDVTypeRow( wb, 0, style_3, "Whole number");
- this.createHeaderRow( wb, 0, style_4 );
-
- short start_row = (short)fSheet.getPhysicalNumberOfRows();
- data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_INTEGER);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
- data_validation.setFirstFormula("2");
- data_validation.setSecondFormula("6");
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 2 and 6 ", true, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)(start_row+1));
- data_validation.setLastRow((short)(start_row+1));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 2 and 6 ", false, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
-
- data_validation.setFirstRow((short)(start_row+2));
- data_validation.setLastRow((short)(start_row+2));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3", false, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
-
- data_validation.setFirstRow((short)(start_row+3));
- data_validation.setLastRow((short)(start_row+3));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3", false, false, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+4));
- data_validation.setLastRow((short)(start_row+4));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3", true, false, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+5));
- data_validation.setLastRow((short)(start_row+5));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3", true, true, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+6));
- data_validation.setLastRow((short)(start_row+6));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
- data_validation.setShowErrorBox(true);
- data_validation.setFirstFormula("4");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 4", true, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)(start_row+7));
- data_validation.setLastRow((short)(start_row+7));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("4");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 4", false, true, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- //"Decimal" validation type
- this.createDVTypeRow( wb, 0, style_3, "Decimal");
- this.createHeaderRow( wb, 0, style_4 );
-
- start_row += (short)(8+4);
- data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_DECIMAL);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
- data_validation.setFirstFormula("2");
- data_validation.setSecondFormula("6");
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 2 and 6 ", true, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)(start_row+1));
- data_validation.setLastRow((short)(start_row+1));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 2 and 6 ", false, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
-
- data_validation.setFirstRow((short)(start_row+2));
- data_validation.setLastRow((short)(start_row+2));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3", false, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
-
- data_validation.setFirstRow((short)(start_row+3));
- data_validation.setLastRow((short)(start_row+3));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3", false, false, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+4));
- data_validation.setLastRow((short)(start_row+4));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3", true, false, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+5));
- data_validation.setLastRow((short)(start_row+5));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3", true, true, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+6));
- data_validation.setLastRow((short)(start_row+6));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
- data_validation.setShowErrorBox(true);
- data_validation.setFirstFormula("4");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 4", true, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)(start_row+7));
- data_validation.setLastRow((short)(start_row+7));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("4");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 4", false, true, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- System.out.println("done !");
-
- //"List" Data Validation type
- /** @todo List*/
- System.out.print(" Create sheet for 'List' Data Validation type ... ");
- fSheet = wb.createSheet("Lists");
-
- this.createDVTypeRow( wb, 1, style_3, "Explicit lists - list items are explicitly provided");
- this.createDVDeescriptionRow( wb, 1, style_3, "Disadvantage - sum of item's length should be less than 255 characters");
- this.createHeaderRow( wb, 1, style_4 );
-
- start_row = (short)fSheet.getPhysicalNumberOfRows();
- data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
- data_validation.setFirstFormula("1+2+3");
- data_validation.setSecondFormula(null);
- data_validation.setSurppressDropDownArrow(false);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", true, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" );
-
- data_validation = new HSSFDataValidation((short)(start_row+1),(short)0,(short)(start_row+1),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
- data_validation.setFirstFormula("4+5+6+7");
- data_validation.setSecondFormula(null);
- data_validation.setSurppressDropDownArrow(false);
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", false, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" );
-
- data_validation = new HSSFDataValidation((short)(start_row+2),(short)0,(short)(start_row+2),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
- data_validation.setFirstFormula("7+21");
- data_validation.setSecondFormula(null);
- data_validation.setSurppressDropDownArrow(true);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", true, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" );
-
- data_validation = new HSSFDataValidation((short)(start_row+3),(short)0,(short)(start_row+3),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
- data_validation.setFirstFormula("8/2");
- data_validation.setSecondFormula(null);
- data_validation.setSurppressDropDownArrow(true);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", false, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" );
-
- this.createDVTypeRow( wb, 1, style_3, "Reference lists - list items are taken from others cells");
- this.createDVDeescriptionRow( wb, 1, style_3, "Advantage - no restriction regarding the sum of item's length");
- this.createHeaderRow( wb, 1, style_4 );
-
- start_row += (short)(4+5);
- String cellStrValue = "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "+
- "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "+
- "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "+
- "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 ";
-
- String strFormula = "$A$100:$A$120";
- data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
- data_validation.setFirstFormula(strFormula);
- data_validation.setSecondFormula(null);
- data_validation.setSurppressDropDownArrow(false);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, true, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" );
-
- data_validation = new HSSFDataValidation((short)(start_row+1),(short)0,(short)(start_row+1),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
- data_validation.setFirstFormula(strFormula);
- data_validation.setSecondFormula(null);
- data_validation.setSurppressDropDownArrow(false);
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, false, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" );
-
- data_validation = new HSSFDataValidation((short)(start_row+2),(short)0,(short)(start_row+2),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
- data_validation.setFirstFormula(strFormula);
- data_validation.setSecondFormula(null);
- data_validation.setSurppressDropDownArrow(true);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, true, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" );
-
- data_validation = new HSSFDataValidation((short)(start_row+3),(short)0,(short)(start_row+3),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
- data_validation.setFirstFormula(strFormula);
- data_validation.setSecondFormula(null);
- data_validation.setSurppressDropDownArrow(true);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, false, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" );
-
- for (int i=100; i<=120; i++)
- {
- HSSFRow currRow = fSheet.createRow(i);
- currRow.createCell((short)0).setCellValue(cellStrValue);
-// currRow.hide( true );
- }
-
- System.out.println("done !");
-
- //Date/Time Validation type
- System.out.print(" Create sheet for 'Date' and 'Time' Data Validation types ... ");
- fSheet = wb.createSheet("Date_Time");
- SimpleDateFormat df = new SimpleDateFormat("m/d/yyyy");
- HSSFDataFormat dataFormat = wb.createDataFormat();
- short fmtDate = dataFormat.getFormat("m/d/yyyy");
- short fmtTime = dataFormat.getFormat("h:mm");
- HSSFCellStyle cellStyle_data = wb.createCellStyle();
- cellStyle_data.setDataFormat(fmtDate);
- HSSFCellStyle cellStyle_time = wb.createCellStyle();
- cellStyle_time.setDataFormat(fmtTime);
-
- this.createDVTypeRow( wb, 2, style_3, "Date ( cells are already formated as date - m/d/yyyy)");
- this.createHeaderRow( wb, 2, style_4 );
-
- start_row = (short)fSheet.getPhysicalNumberOfRows();
- data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_DATE);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
-
- data_validation.setFirstFormula( String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("1/2/2004"))) );
- data_validation.setSecondFormula( String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("1/6/2004"))) );
-
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 1/2/2004 and 1/6/2004 ", true, true, true );
- this.setCellFormat( fSheet, cellStyle_data );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)(start_row+1));
- data_validation.setLastRow((short)(start_row+1));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 1/2/2004 and 1/6/2004 ", false, true, true );
- this.setCellFormat( fSheet, cellStyle_data );
- this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
-
- data_validation.setFirstRow((short)(start_row+2));
- data_validation.setLastRow((short)(start_row+2));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3/2/2004", false, false, true );
- this.setCellFormat( fSheet, cellStyle_data );
- this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
-
- data_validation.setFirstRow((short)(start_row+3));
- data_validation.setLastRow((short)(start_row+3));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3/2/2004", false, false, false );
- this.setCellFormat( fSheet, cellStyle_data );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+4));
- data_validation.setLastRow((short)(start_row+4));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3/2/2004", true, false, false );
- this.setCellFormat( fSheet, cellStyle_data );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+5));
- data_validation.setLastRow((short)(start_row+5));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3/2/2004", true, true, false );
- this.setCellFormat( fSheet, cellStyle_data );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+6));
- data_validation.setLastRow((short)(start_row+6));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
- data_validation.setShowErrorBox(true);
- data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 3/2/2004", true, false, true );
- this.setCellFormat( fSheet, cellStyle_data );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)(start_row+7));
- data_validation.setLastRow((short)(start_row+7));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/4/2004"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 3/4/2004", false, true, false );
- this.setCellFormat( fSheet, cellStyle_data );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- //"Time" validation type
- this.createDVTypeRow( wb, 2, style_3, "Time ( cells are already formated as time - h:mm)");
- this.createHeaderRow( wb, 2, style_4 );
-
- df = new SimpleDateFormat("hh:mm");
-
- start_row += (short)(8+4);
- data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_TIME);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
- data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("12:00"))));
- data_validation.setSecondFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("16:00"))));
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 12:00 and 16:00 ", true, true, true );
- this.setCellFormat( fSheet, cellStyle_time );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)(start_row+1));
- data_validation.setLastRow((short)(start_row+1));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 12:00 and 16:00 ", false, true, true );
- this.setCellFormat( fSheet, cellStyle_time );
- this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
-
- data_validation.setFirstRow((short)(start_row+2));
- data_validation.setLastRow((short)(start_row+2));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("13:35"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 13:35", false, false, true );
- this.setCellFormat( fSheet, cellStyle_time );
- this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
-
- data_validation.setFirstRow((short)(start_row+3));
- data_validation.setLastRow((short)(start_row+3));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("13:35"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 13:35", false, false, false );
- this.setCellFormat( fSheet, cellStyle_time );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+4));
- data_validation.setLastRow((short)(start_row+4));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("12:00"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 12:00", true, false, false );
- this.setCellFormat( fSheet, cellStyle_time );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+5));
- data_validation.setLastRow((short)(start_row+5));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("12:00"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 12:00", true, true, false );
- this.setCellFormat( fSheet, cellStyle_time );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)(start_row+6));
- data_validation.setLastRow((short)(start_row+6));
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
- data_validation.setShowErrorBox(true);
- data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("14:00"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 14:00", true, false, true );
- this.setCellFormat( fSheet, cellStyle_time );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)(start_row+7));
- data_validation.setLastRow((short)(start_row+7));
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("14:00"))));
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 14:00", false, true, false );
- this.setCellFormat( fSheet, cellStyle_time );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- System.out.println("done !");
-
- //"Text length" validation type
- System.out.print(" Create sheet for 'Text length' Data Validation type... ");
- fSheet = wb.createSheet("Text length");
- this.createHeaderRow( wb, 3, style_4 );
-
- data_validation = new HSSFDataValidation((short)1,(short)0,(short)1,(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_TEXT_LENGTH);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
- data_validation.setFirstFormula("2");
- data_validation.setSecondFormula("6");
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 2 and 6 ", true, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)2);
- data_validation.setLastRow((short)2);
- data_validation.setEmptyCellAllowed(false);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 2 and 6 ", false, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
-
- data_validation.setFirstRow((short)3);
- data_validation.setLastRow((short)3);
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3", false, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
-
- data_validation.setFirstRow((short)4);
- data_validation.setLastRow((short)4);
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3", false, false, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)5);
- data_validation.setLastRow((short)5);
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3", true, false, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)6);
- data_validation.setLastRow((short)6);
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("3");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3", true, true, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
-
- data_validation.setFirstRow((short)7);
- data_validation.setLastRow((short)7);
- data_validation.setEmptyCellAllowed(true);
- data_validation.setShowPromptBox(false);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
- data_validation.setShowErrorBox(true);
- data_validation.setFirstFormula("4");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 4", true, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation.setFirstRow((short)8);
- data_validation.setLastRow((short)8);
- data_validation.setEmptyCellAllowed(false);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(false);
- data_validation.setFirstFormula("4");
- data_validation.setSecondFormula(null);
- data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 4", false, true, false );
- this.writeOtherSettings( fSheet, style_1, "-" );
- System.out.println("done !");
-
- //Custom Validation type
- System.out.print(" Create sheet for 'Custom' Data Validation type ... ");
- fSheet = wb.createSheet("Custom");
- this.createHeaderRow( wb, 4, style_4 );
-
- data_validation = new HSSFDataValidation((short)1,(short)0,(short)1,(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_FORMULA);
- data_validation.setFirstFormula("ISNUMBER($A2)");
- data_validation.setSecondFormula(null);
- data_validation.setShowPromptBox(true);
- data_validation.setShowErrorBox(true);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "ISNUMBER(A2)", true, true, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
-
- data_validation = new HSSFDataValidation((short)2,(short)0,(short)2,(short)0);
- data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_FORMULA);
- data_validation.setFirstFormula("IF(SUM(A2:A3)=5,TRUE,FALSE)");
- data_validation.setSecondFormula(null);
- data_validation.setShowPromptBox(false);
- data_validation.setShowErrorBox(true);
- data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
- data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
- data_validation.setEmptyCellAllowed(false);
- fSheet.addValidationData(data_validation);
- this.writeDataValidationSettings( fSheet, style_1, style_2, "IF(SUM(A2:A3)=5,TRUE,FALSE)", false, false, true );
- this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
-
- System.out.println("done !");
-
- //so , everything it's ok for now ; it remains for you to open the file
- System.out.println("\n Everything it's ok since we've got so far -:) !\n"+
- " In order to complete the test , it remains for you to open the file \n"+
- " and see if there are four sheets , as described !");
- System.out.println(" File was saved in \""+resultFile+"\"");
-
- FileOutputStream fileOut = new FileOutputStream(resultFile);
- wb.write(fileOut);
- fileOut.close();
- }
+public final class TestDataValidation extends TestCase {
+
+ /** Convenient access to ERROR_STYLE constants */
+ private static final HSSFDataValidation.ErrorStyle ES = null;
+ /** Convenient access to OPERATOR constants */
+ private static final DVConstraint.ValidationType VT = null;
+ /** Convenient access to OPERATOR constants */
+ private static final DVConstraint.OperatorType OP = null;
+
+ private static void log(String msg) {
+ if (false) { // successful tests should be silent
+ System.out.println(msg);
+ }
+ }
+
+ private static final class ValidationAdder {
+
+ private final HSSFCellStyle _style_1;
+ private final HSSFCellStyle _style_2;
+ private final int _validationType;
+ private final HSSFSheet _sheet;
+ private int _currentRowIndex;
+ private final HSSFCellStyle _cellStyle;
+
+ public ValidationAdder(HSSFSheet fSheet, HSSFCellStyle style_1, HSSFCellStyle style_2,
+ HSSFCellStyle cellStyle, int validationType) {
+ _sheet = fSheet;
+ _style_1 = style_1;
+ _style_2 = style_2;
+ _cellStyle = cellStyle;
+ _validationType = validationType;
+ _currentRowIndex = fSheet.getPhysicalNumberOfRows();
+ }
+ public void addValidation(int operatorType, String firstFormula, String secondFormula,
+ int errorStyle, String ruleDescr, String promptDescr,
+ boolean allowEmpty, boolean inputBox, boolean errorBox) {
+ String[] explicitListValues = null;
+
+ addValidationInternal(operatorType, firstFormula, secondFormula, errorStyle, ruleDescr,
+ promptDescr, allowEmpty, inputBox, errorBox, true,
+ explicitListValues);
+ }
- private void createDVTypeRow( HSSFWorkbook wb, int sheetNo , HSSFCellStyle cellStyle, String strTypeDescription)
- {
- HSSFSheet sheet = wb.getSheetAt(sheetNo);
- HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
- row = sheet.createRow(sheet.getPhysicalNumberOfRows());
- sheet.addMergedRegion(new Region((short)(sheet.getPhysicalNumberOfRows()-1),(short)0,(short)(sheet.getPhysicalNumberOfRows()-1),(short)5));
- HSSFCell cell = row.createCell((short)0);
- cell.setCellValue(strTypeDescription);
- cell.setCellStyle(cellStyle);
- row = sheet.createRow(sheet.getPhysicalNumberOfRows());
- }
+ private void addValidationInternal(int operatorType, String firstFormula,
+ String secondFormula, int errorStyle, String ruleDescr, String promptDescr,
+ boolean allowEmpty, boolean inputBox, boolean errorBox, boolean suppressDropDown,
+ String[] explicitListValues) {
+ int rowNum = _currentRowIndex++;
+
+ DVConstraint dc = createConstraint(operatorType, firstFormula, secondFormula, explicitListValues);
+
+ HSSFDataValidation dv = new HSSFDataValidation(new CellRangeAddressList(rowNum, rowNum, 0, 0), dc);
+
+ dv.setEmptyCellAllowed(allowEmpty);
+ dv.setErrorStyle(errorStyle);
+ dv.createErrorBox("Invalid Input", "Something is wrong - check condition!");
+ dv.createPromptBox("Validated Cell", "Allowable values have been restricted");
+
+ dv.setShowPromptBox(inputBox);
+ dv.setShowErrorBox(errorBox);
+ dv.setSuppressDropDownArrow(suppressDropDown);
+
+
+ _sheet.addValidationData(dv);
+ writeDataValidationSettings(_sheet, _style_1, _style_2, ruleDescr, allowEmpty,
+ inputBox, errorBox);
+ if (_cellStyle != null) {
+ HSSFRow row = _sheet.getRow(_sheet.getPhysicalNumberOfRows() - 1);
+ HSSFCell cell = row.createCell((short) 0);
+ cell.setCellStyle(_cellStyle);
+ }
+ writeOtherSettings(_sheet, _style_1, promptDescr);
+ }
+ private DVConstraint createConstraint(int operatorType, String firstFormula,
+ String secondFormula, String[] explicitListValues) {
+ if (_validationType == VT.LIST) {
+ if (explicitListValues != null) {
+ return DVConstraint.createExplicitListConstraint(explicitListValues);
+ }
+ return DVConstraint.createFormulaListConstraint(firstFormula);
+ }
+ if (_validationType == VT.TIME) {
+ return DVConstraint.createTimeConstraint(operatorType, firstFormula, secondFormula);
+ }
+ if (_validationType == VT.DATE) {
+ return DVConstraint.createDateConstraint(operatorType, firstFormula, secondFormula, null);
+ }
+ if (_validationType == VT.FORMULA) {
+ return DVConstraint.createFormulaConstraint(firstFormula);
+ }
+ return DVConstraint.createNumericConstraint(_validationType, operatorType, firstFormula, secondFormula);
+ }
+ /**
+ * writes plain text values into cells in a tabular format to form comments readable from within
+ * the spreadsheet.
+ */
+ private static void writeDataValidationSettings(HSSFSheet sheet, HSSFCellStyle style_1,
+ HSSFCellStyle style_2, String strCondition, boolean allowEmpty, boolean inputBox,
+ boolean errorBox) {
+ HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
+ // condition's string
+ HSSFCell cell = row.createCell((short) 1);
+ cell.setCellStyle(style_1);
+ setCellValue(cell, strCondition);
+ // allow empty cells
+ cell = row.createCell((short) 2);
+ cell.setCellStyle(style_2);
+ setCellValue(cell, ((allowEmpty) ? "yes" : "no"));
+ // show input box
+ cell = row.createCell((short) 3);
+ cell.setCellStyle(style_2);
+ setCellValue(cell, ((inputBox) ? "yes" : "no"));
+ // show error box
+ cell = row.createCell((short) 4);
+ cell.setCellStyle(style_2);
+ setCellValue(cell, ((errorBox) ? "yes" : "no"));
+ }
+ private static void writeOtherSettings(HSSFSheet sheet, HSSFCellStyle style,
+ String strStettings) {
+ HSSFRow row = sheet.getRow(sheet.getPhysicalNumberOfRows() - 1);
+ HSSFCell cell = row.createCell((short) 5);
+ cell.setCellStyle(style);
+ setCellValue(cell, strStettings);
+ }
+ public void addListValidation(String[] explicitListValues, String listFormula, String listValsDescr,
+ boolean allowEmpty, boolean suppressDropDown) {
+ String promptDescr = (allowEmpty ? "empty ok" : "not empty")
+ + ", " + (suppressDropDown ? "no drop-down" : "drop-down");
+ addValidationInternal(VT.LIST, listFormula, null, ES.STOP, listValsDescr, promptDescr,
+ allowEmpty, false, true, suppressDropDown, explicitListValues);
+ }
+ }
- private void createDVDeescriptionRow( HSSFWorkbook wb, int sheetNo , HSSFCellStyle cellStyle, String strTypeDescription )
- {
- HSSFSheet sheet = wb.getSheetAt(sheetNo);
- HSSFRow row = sheet.getRow(sheet.getPhysicalNumberOfRows()-1);
- sheet.addMergedRegion(new Region((short)(sheet.getPhysicalNumberOfRows()-1),(short)0,(short)(sheet.getPhysicalNumberOfRows()-1),(short)5));
- HSSFCell cell = row.createCell((short)0);
- cell.setCellValue(strTypeDescription);
- cell.setCellStyle(cellStyle);
- row = sheet.createRow(sheet.getPhysicalNumberOfRows());
- }
+ /**
+ * Manages the cell styles used for formatting the output spreadsheet
+ */
+ private static final class WorkbookFormatter {
+
+ private final HSSFWorkbook _wb;
+ private final HSSFCellStyle _style_1;
+ private final HSSFCellStyle _style_2;
+ private final HSSFCellStyle _style_3;
+ private final HSSFCellStyle _style_4;
+ private HSSFSheet _currentSheet;
+
+ public WorkbookFormatter(HSSFWorkbook wb) {
+ _wb = wb;
+ _style_1 = createStyle( wb, HSSFCellStyle.ALIGN_LEFT );
+ _style_2 = createStyle( wb, HSSFCellStyle.ALIGN_CENTER );
+ _style_3 = createStyle( wb, HSSFCellStyle.ALIGN_CENTER, HSSFColor.GREY_25_PERCENT.index, true );
+ _style_4 = createHeaderStyle(wb);
+ }
+
+ private static HSSFCellStyle createStyle(HSSFWorkbook wb, short h_align, short color,
+ boolean bold) {
+ HSSFFont font = wb.createFont();
+ if (bold) {
+ font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
+ }
- private void createHeaderRow( HSSFWorkbook wb, int sheetNo , HSSFCellStyle cellStyle )
- {
- HSSFSheet sheet = wb.getSheetAt(sheetNo);
- HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
- row.setHeight((short)400);
- for ( int i=0; i<6; i++ )
- {
- row.createCell((short)i).setCellStyle( cellStyle );
- if ( i==2 || i==3 || i==4 )
- {
- sheet.setColumnWidth( (short) i, (short) 3500);
- }
- else if ( i== 5)
- {
- sheet.setColumnWidth( (short) i, (short) 10000);
- }
- else
- {
- sheet.setColumnWidth( (short) i, (short) 8000);
- }
- }
- HSSFCell cell = row.getCell((short)0);
- cell.setCellValue("Data validation cells");
- cell = row.getCell((short)1);
- cell.setCellValue("Condition");
- cell = row.getCell((short)2);
- cell.setCellValue("Allow blank");
- cell = row.getCell((short)3);
- cell.setCellValue("Prompt box");
- cell = row.getCell((short)4);
- cell.setCellValue("Error box");
- cell = row.getCell((short)5);
- cell.setCellValue("Other settings");
- }
+ HSSFCellStyle cellStyle = wb.createCellStyle();
+ cellStyle.setFont(font);
+ cellStyle.setFillForegroundColor(color);
+ cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
+ cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
+ cellStyle.setAlignment(h_align);
+ cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
+ cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
+ cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
+ cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
+ cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
+ cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
+ cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
+ cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
+
+ return cellStyle;
+ }
- private HSSFCellStyle createHeaderStyle(HSSFWorkbook wb)
- {
- HSSFFont font = wb.createFont();
- font.setColor( HSSFColor.WHITE.index );
- font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
-
- HSSFCellStyle cellStyle = wb.createCellStyle();
- cellStyle.setFillForegroundColor(HSSFColor.BLUE_GREY.index);
- cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
- cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
- cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
- cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
- cellStyle.setLeftBorderColor(HSSFColor.WHITE.index);
- cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
- cellStyle.setTopBorderColor(HSSFColor.WHITE.index);
- cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
- cellStyle.setRightBorderColor(HSSFColor.WHITE.index);
- cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
- cellStyle.setBottomBorderColor(HSSFColor.WHITE.index);
- cellStyle.setFont(font);
- return cellStyle;
- }
+ private static HSSFCellStyle createStyle(HSSFWorkbook wb, short h_align) {
+ return createStyle(wb, h_align, HSSFColor.WHITE.index, false);
+ }
+ private static HSSFCellStyle createHeaderStyle(HSSFWorkbook wb) {
+ HSSFFont font = wb.createFont();
+ font.setColor( HSSFColor.WHITE.index );
+ font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
+
+ HSSFCellStyle cellStyle = wb.createCellStyle();
+ cellStyle.setFillForegroundColor(HSSFColor.BLUE_GREY.index);
+ cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
+ cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
+ cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
+ cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
+ cellStyle.setLeftBorderColor(HSSFColor.WHITE.index);
+ cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
+ cellStyle.setTopBorderColor(HSSFColor.WHITE.index);
+ cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
+ cellStyle.setRightBorderColor(HSSFColor.WHITE.index);
+ cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
+ cellStyle.setBottomBorderColor(HSSFColor.WHITE.index);
+ cellStyle.setFont(font);
+ return cellStyle;
+ }
+
- private HSSFCellStyle createStyle( HSSFWorkbook wb, short h_align, short color, boolean bold )
- {
- HSSFFont font = wb.createFont();
- if ( bold )
- {
- font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
- }
-
- HSSFCellStyle cellStyle = wb.createCellStyle();
- cellStyle.setFont(font);
- cellStyle.setFillForegroundColor(color);
- cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
- cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
- cellStyle.setAlignment(h_align);
- cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
- cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
- cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
- cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
- cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
- cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
- cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
- cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
-
- return cellStyle;
- }
+ public HSSFSheet createSheet(String sheetName) {
+ _currentSheet = _wb.createSheet(sheetName);
+ return _currentSheet;
+ }
+ public void createDVTypeRow(String strTypeDescription) {
+ HSSFSheet sheet = _currentSheet;
+ HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
+ row = sheet.createRow(sheet.getPhysicalNumberOfRows());
+ sheet.addMergedRegion(new Region((short) (sheet.getPhysicalNumberOfRows() - 1),
+ (short) 0, (short) (sheet.getPhysicalNumberOfRows() - 1), (short) 5));
+ HSSFCell cell = row.createCell((short) 0);
+ setCellValue(cell, strTypeDescription);
+ cell.setCellStyle(_style_3);
+ row = sheet.createRow(sheet.getPhysicalNumberOfRows());
+ }
+
+ public void createHeaderRow() {
+ HSSFSheet sheet = _currentSheet;
+ HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
+ row.setHeight((short) 400);
+ for (int i = 0; i < 6; i++) {
+ row.createCell((short) i).setCellStyle(_style_4);
+ if (i == 2 || i == 3 || i == 4) {
+ sheet.setColumnWidth((short) i, (short) 3500);
+ } else if (i == 5) {
+ sheet.setColumnWidth((short) i, (short) 10000);
+ } else {
+ sheet.setColumnWidth((short) i, (short) 8000);
+ }
+ }
+ HSSFCell cell = row.getCell((short) 0);
+ setCellValue(cell, "Data validation cells");
+ cell = row.getCell((short) 1);
+ setCellValue(cell, "Condition");
+ cell = row.getCell((short) 2);
+ setCellValue(cell, "Allow blank");
+ cell = row.getCell((short) 3);
+ setCellValue(cell, "Prompt box");
+ cell = row.getCell((short) 4);
+ setCellValue(cell, "Error box");
+ cell = row.getCell((short) 5);
+ setCellValue(cell, "Other settings");
+ }
- private HSSFCellStyle createStyle( HSSFWorkbook wb, short h_align )
- {
- return this.createStyle(wb, h_align, HSSFColor.WHITE.index, false);
- }
+ public ValidationAdder createValidationAdder(HSSFCellStyle cellStyle, int dataValidationType) {
+ return new ValidationAdder(_currentSheet, _style_1, _style_2, cellStyle, dataValidationType);
+ }
- private void writeDataValidationSettings( HSSFSheet sheet, HSSFCellStyle style_1, HSSFCellStyle style_2, String strCondition, boolean allowEmpty, boolean inputBox, boolean errorBox )
- {
- HSSFRow row = sheet.createRow( sheet.getPhysicalNumberOfRows() );
- //condition's string
- HSSFCell cell = row.createCell((short)1);
- cell.setCellStyle(style_1);
- cell.setCellValue(strCondition);
- //allow empty cells
- cell = row.createCell((short)2);
- cell.setCellStyle(style_2);
- cell.setCellValue( ((allowEmpty) ? "yes" : "no") );
- //show input box
- cell = row.createCell((short)3);
- cell.setCellStyle(style_2);
- cell.setCellValue( ((inputBox) ? "yes" : "no") );
- //show error box
- cell = row.createCell((short)4);
- cell.setCellStyle(style_2);
- cell.setCellValue( ((errorBox) ? "yes" : "no") );
- }
+ public void createDVDescriptionRow(String strTypeDescription) {
+ HSSFSheet sheet = _currentSheet;
+ HSSFRow row = sheet.getRow(sheet.getPhysicalNumberOfRows()-1);
+ sheet.addMergedRegion(new Region((short)(sheet.getPhysicalNumberOfRows()-1),(short)0,(short)(sheet.getPhysicalNumberOfRows()-1),(short)5));
+ HSSFCell cell = row.createCell((short)0);
+ setCellValue(cell, strTypeDescription);
+ cell.setCellStyle(_style_3);
+ row = sheet.createRow(sheet.getPhysicalNumberOfRows());
+ }
+ }
+
+
+ private void addCustomValidations(WorkbookFormatter wf) {
+ wf.createSheet("Custom");
+ wf.createHeaderRow();
- private void setCellFormat( HSSFSheet sheet, HSSFCellStyle cell_style )
- {
- HSSFRow row = sheet.getRow( sheet.getPhysicalNumberOfRows() -1 );
- HSSFCell cell = row.createCell((short)0);
- cell.setCellStyle(cell_style);
- }
+ ValidationAdder va = wf.createValidationAdder(null, VT.FORMULA);
+ va.addValidation(OP.BETWEEN, "ISNUMBER($A2)", null, ES.STOP, "ISNUMBER(A2)", "Error box type = STOP", true, true, true);
+ va.addValidation(OP.BETWEEN, "IF(SUM(A2:A3)=5,TRUE,FALSE)", null, ES.WARNING, "IF(SUM(A2:A3)=5,TRUE,FALSE)", "Error box type = WARNING", false, false, true);
+ }
+
+ private static void addSimpleNumericValidations(WorkbookFormatter wf) {
+ // data validation's number types
+ wf.createSheet("Numbers");
+
+ // "Whole number" validation type
+ wf.createDVTypeRow("Whole number");
+ wf.createHeaderRow();
+
+ ValidationAdder va = wf.createValidationAdder(null, VT.INTEGER);
+ va.addValidation(OP.BETWEEN, "2", "6", ES.STOP, "Between 2 and 6 ", "Error box type = STOP", true, true, true);
+ va.addValidation(OP.NOT_BETWEEN, "2", "6", ES.INFO, "Not between 2 and 6 ", "Error box type = INFO", false, true, true);
+ va.addValidation(OP.EQUAL, "=3+2", null, ES.WARNING, "Equal to (3+2)", "Error box type = WARNING", false, false, true);
+ va.addValidation(OP.NOT_EQUAL, "3", null, ES.WARNING, "Not equal to 3", "-", false, false, false);
+ va.addValidation(OP.GREATER_THAN, "3", null, ES.WARNING, "Greater than 3", "-", true, false, false);
+ va.addValidation(OP.LESS_THAN, "3", null, ES.WARNING, "Less than 3", "-", true, true, false);
+ va.addValidation(OP.GREATER_OR_EQUAL, "4", null, ES.STOP, "Greater than or equal to 4", "Error box type = STOP", true, false, true);
+ va.addValidation(OP.LESS_OR_EQUAL, "4", null, ES.STOP, "Less than or equal to 4", "-", false, true, false);
+
+ // "Decimal" validation type
+ wf.createDVTypeRow("Decimal");
+ wf.createHeaderRow();
+
+ va = wf.createValidationAdder(null, VT.DECIMAL);
+ va.addValidation(OP.BETWEEN, "2", "6", ES.STOP, "Between 2 and 6 ", "Error box type = STOP", true, true, true);
+ va.addValidation(OP.NOT_BETWEEN, "2", "6", ES.INFO, "Not between 2 and 6 ", "Error box type = INFO", false, true, true);
+ va.addValidation(OP.EQUAL, "3", null, ES.WARNING, "Equal to 3", "Error box type = WARNING", false, false, true);
+ va.addValidation(OP.NOT_EQUAL, "3", null, ES.WARNING, "Not equal to 3", "-", false, false, false);
+ va.addValidation(OP.GREATER_THAN, "=12/6", null, ES.WARNING, "Greater than (12/6)", "-", true, false, false);
+ va.addValidation(OP.LESS_THAN, "3", null, ES.WARNING, "Less than 3", "-", true, true, false);
+ va.addValidation(OP.GREATER_OR_EQUAL, "4", null, ES.STOP, "Greater than or equal to 4", "Error box type = STOP", true, false, true);
+ va.addValidation(OP.LESS_OR_EQUAL, "4", null, ES.STOP, "Less than or equal to 4", "-", false, true, false);
+ }
+
+ private static void addListValidations(WorkbookFormatter wf, HSSFWorkbook wb) {
+ final String cellStrValue
+ = "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "
+ + "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "
+ + "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "
+ + "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 ";
+ final String dataSheetName = "list_data";
+ // "List" Data Validation type
+ HSSFSheet fSheet = wf.createSheet("Lists");
+ HSSFSheet dataSheet = wb.createSheet(dataSheetName);
+
+
+ wf.createDVTypeRow("Explicit lists - list items are explicitly provided");
+ wf.createDVDescriptionRow("Disadvantage - sum of item's length should be less than 255 characters");
+ wf.createHeaderRow();
+
+ ValidationAdder va = wf.createValidationAdder(null, VT.LIST);
+ String listValsDescr = "POIFS,HSSF,HWPF,HPSF";
+ String[] listVals = listValsDescr.split(",");
+ va.addListValidation(listVals, null, listValsDescr, false, false);
+ va.addListValidation(listVals, null, listValsDescr, false, true);
+ va.addListValidation(listVals, null, listValsDescr, true, false);
+ va.addListValidation(listVals, null, listValsDescr, true, true);
+
+
+
+ wf.createDVTypeRow("Reference lists - list items are taken from others cells");
+ wf.createDVDescriptionRow("Advantage - no restriction regarding the sum of item's length");
+ wf.createHeaderRow();
+ va = wf.createValidationAdder(null, VT.LIST);
+ String strFormula = "$A$30:$A$39";
+ va.addListValidation(null, strFormula, strFormula, false, false);
+
+ strFormula = dataSheetName + "!$A$1:$A$10";
+ va.addListValidation(null, strFormula, strFormula, false, false);
+ HSSFName namedRange = wb.createName();
+ namedRange.setNameName("myName");
+ namedRange.setReference(dataSheetName + "!$A$2:$A$7");
+ strFormula = "myName";
+ va.addListValidation(null, strFormula, strFormula, false, false);
+ strFormula = "offset(myName, 2, 1, 4, 2)"; // Note about last param '2':
+ // - Excel expects single row or single column when entered in UI, but process this OK otherwise
+ va.addListValidation(null, strFormula, strFormula, false, false);
+
+ // add list data on same sheet
+ for (int i = 0; i < 10; i++) {
+ HSSFRow currRow = fSheet.createRow(i + 29);
+ setCellValue(currRow.createCell((short) 0), cellStrValue);
+ }
+ // add list data on another sheet
+ for (int i = 0; i < 10; i++) {
+ HSSFRow currRow = dataSheet.createRow(i + 0);
+ setCellValue(currRow.createCell((short) 0), "Data a" + i);
+ setCellValue(currRow.createCell((short) 1), "Data b" + i);
+ setCellValue(currRow.createCell((short) 2), "Data c" + i);
+ }
+ }
+
+ private static void addDateTimeValidations(WorkbookFormatter wf, HSSFWorkbook wb) {
+ wf.createSheet("Dates and Times");
+
+ HSSFDataFormat dataFormat = wb.createDataFormat();
+ short fmtDate = dataFormat.getFormat("m/d/yyyy");
+ short fmtTime = dataFormat.getFormat("h:mm");
+ HSSFCellStyle cellStyle_date = wb.createCellStyle();
+ cellStyle_date.setDataFormat(fmtDate);
+ HSSFCellStyle cellStyle_time = wb.createCellStyle();
+ cellStyle_time.setDataFormat(fmtTime);
+
+ wf.createDVTypeRow("Date ( cells are already formated as date - m/d/yyyy)");
+ wf.createHeaderRow();
+
+ ValidationAdder va = wf.createValidationAdder(cellStyle_date, VT.DATE);
+ va.addValidation(OP.BETWEEN, "2004/01/02", "2004/01/06", ES.STOP, "Between 1/2/2004 and 1/6/2004 ", "Error box type = STOP", true, true, true);
+ va.addValidation(OP.NOT_BETWEEN, "2004/01/01", "2004/01/06", ES.INFO, "Not between 1/2/2004 and 1/6/2004 ", "Error box type = INFO", false, true, true);
+ va.addValidation(OP.EQUAL, "2004/03/02", null, ES.WARNING, "Equal to 3/2/2004", "Error box type = WARNING", false, false, true);
+ va.addValidation(OP.NOT_EQUAL, "2004/03/02", null, ES.WARNING, "Not equal to 3/2/2004", "-", false, false, false);
+ va.addValidation(OP.GREATER_THAN,"=DATEVALUE(\"4-Jul-2001\")", null, ES.WARNING, "Greater than DATEVALUE('4-Jul-2001')", "-", true, false, false);
+ va.addValidation(OP.LESS_THAN, "2004/03/02", null, ES.WARNING, "Less than 3/2/2004", "-", true, true, false);
+ va.addValidation(OP.GREATER_OR_EQUAL, "2004/03/02", null, ES.STOP, "Greater than or equal to 3/2/2004", "Error box type = STOP", true, false, true);
+ va.addValidation(OP.LESS_OR_EQUAL, "2004/03/04", null, ES.STOP, "Less than or equal to 3/4/2004", "-", false, true, false);
+
+ // "Time" validation type
+ wf.createDVTypeRow("Time ( cells are already formated as time - h:mm)");
+ wf.createHeaderRow();
+
+ va = wf.createValidationAdder(cellStyle_time, VT.TIME);
+ va.addValidation(OP.BETWEEN, "12:00", "16:00", ES.STOP, "Between 12:00 and 16:00 ", "Error box type = STOP", true, true, true);
+ va.addValidation(OP.NOT_BETWEEN, "12:00", "16:00", ES.INFO, "Not between 12:00 and 16:00 ", "Error box type = INFO", false, true, true);
+ va.addValidation(OP.EQUAL, "13:35", null, ES.WARNING, "Equal to 13:35", "Error box type = WARNING", false, false, true);
+ va.addValidation(OP.NOT_EQUAL, "13:35", null, ES.WARNING, "Not equal to 13:35", "-", false, false, false);
+ va.addValidation(OP.GREATER_THAN,"12:00", null, ES.WARNING, "Greater than 12:00", "-", true, false, false);
+ va.addValidation(OP.LESS_THAN, "=1/2", null, ES.WARNING, "Less than (1/2) -> 12:00", "-", true, true, false);
+ va.addValidation(OP.GREATER_OR_EQUAL, "14:00", null, ES.STOP, "Greater than or equal to 14:00", "Error box type = STOP", true, false, true);
+ va.addValidation(OP.LESS_OR_EQUAL,"14:00", null, ES.STOP, "Less than or equal to 14:00", "-", false, true, false);
+ }
+
+ private static void addTextLengthValidations(WorkbookFormatter wf) {
+ wf.createSheet("Text lengths");
+ wf.createHeaderRow();
+
+ ValidationAdder va = wf.createValidationAdder(null, VT.TEXT_LENGTH);
+ va.addValidation(OP.BETWEEN, "2", "6", ES.STOP, "Between 2 and 6 ", "Error box type = STOP", true, true, true);
+ va.addValidation(OP.NOT_BETWEEN, "2", "6", ES.INFO, "Not between 2 and 6 ", "Error box type = INFO", false, true, true);
+ va.addValidation(OP.EQUAL, "3", null, ES.WARNING, "Equal to 3", "Error box type = WARNING", false, false, true);
+ va.addValidation(OP.NOT_EQUAL, "3", null, ES.WARNING, "Not equal to 3", "-", false, false, false);
+ va.addValidation(OP.GREATER_THAN, "3", null, ES.WARNING, "Greater than 3", "-", true, false, false);
+ va.addValidation(OP.LESS_THAN, "3", null, ES.WARNING, "Less than 3", "-", true, true, false);
+ va.addValidation(OP.GREATER_OR_EQUAL, "4", null, ES.STOP, "Greater than or equal to 4", "Error box type = STOP", true, false, true);
+ va.addValidation(OP.LESS_OR_EQUAL, "4", null, ES.STOP, "Less than or equal to 4", "-", false, true, false);
+ }
+
+ public void testDataValidation() {
+ log("\nTest no. 2 - Test Excel's Data validation mechanism");
+ HSSFWorkbook wb = new HSSFWorkbook();
+ WorkbookFormatter wf = new WorkbookFormatter(wb);
+
+ log(" Create sheet for Data Validation's number types ... ");
+ addSimpleNumericValidations(wf);
+ log("done !");
+
+ log(" Create sheet for 'List' Data Validation type ... ");
+ addListValidations(wf, wb);
+ log("done !");
+
+ log(" Create sheet for 'Date' and 'Time' Data Validation types ... ");
+ addDateTimeValidations(wf, wb);
+ log("done !");
+
+ log(" Create sheet for 'Text length' Data Validation type... ");
+ addTextLengthValidations(wf);
+ log("done !");
+
+ // Custom Validation type
+ log(" Create sheet for 'Custom' Data Validation type ... ");
+ addCustomValidations(wf);
+ log("done !");
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(22000);
+ try {
+ wb.write(baos);
+ baos.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ byte[] generatedContent = baos.toByteArray();
+ boolean isSame;
+ if (false) {
+ // TODO - add proof spreadsheet and compare
+ InputStream proofStream = HSSFTestDataSamples.openSampleFileStream("TestDataValidation.xls");
+ isSame = compareStreams(proofStream, generatedContent);
+ }
+ isSame = true;
+
+ if (isSame) {
+ return;
+ }
+ File tempDir = new File(System.getProperty("java.io.tmpdir"));
+ File generatedFile = new File(tempDir, "GeneratedTestDataValidation.xls");
+ try {
+ FileOutputStream fileOut = new FileOutputStream(generatedFile);
+ fileOut.write(generatedContent);
+ fileOut.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ PrintStream ps = System.out;
+
+ ps.println("This test case has failed because the generated file differs from proof copy '"
+ ); // TODO+ proofFile.getAbsolutePath() + "'.");
+ ps.println("The cause is usually a change to this test, or some common spreadsheet generation code. "
+ + "The developer has to decide whether the changes were wanted or unwanted.");
+ ps.println("If the changes to the generated version were unwanted, "
+ + "make the fix elsewhere (do not modify this test or the proof spreadsheet to get the test working).");
+ ps.println("If the changes were wanted, make sure to open the newly generated file in Excel "
+ + "and verify it manually. The new proof file should be submitted after it is verified to be correct.");
+ ps.println("");
+ ps.println("One other possible (but less likely) cause of a failed test is a problem in the "
+ + "comparison logic used here. Perhaps some extra file regions need to be ignored.");
+ ps.println("The generated file has been saved to '" + generatedFile.getAbsolutePath() + "' for manual inspection.");
+
+ fail("Generated file differs from proof copy. See sysout comments for details on how to fix.");
+
+ }
+
+ private static boolean compareStreams(InputStream isA, byte[] generatedContent) {
+
+ InputStream isB = new ByteArrayInputStream(generatedContent);
+
+ // The allowable regions where the generated file can differ from the
+ // proof should be small (i.e. much less than 1K)
+ int[] allowableDifferenceRegions = {
+ 0x0228, 16, // a region of the file containing the OS username
+ 0x506C, 8, // See RootProperty (super fields _seconds_2 and _days_2)
+ };
+ int[] diffs = StreamUtility.diffStreams(isA, isB, allowableDifferenceRegions);
+ if (diffs == null) {
+ return true;
+ }
+ System.err.println("Diff from proof: ");
+ for (int i = 0; i < diffs.length; i++) {
+ System.err.println("diff at offset: 0x" + Integer.toHexString(diffs[i]));
+ }
+ return false;
+ }
+
- private void writeOtherSettings( HSSFSheet sheet, HSSFCellStyle style, String strStettings )
- {
- HSSFRow row = sheet.getRow( sheet.getPhysicalNumberOfRows() -1 );
- HSSFCell cell = row.createCell((short)5);
- cell.setCellStyle(style);
- cell.setCellValue(strStettings);
- }
+
+
+ /* package */ static void setCellValue(HSSFCell cell, String text) {
+ cell.setCellValue(new HSSFRichTextString(text));
+
+ }
public void testAddToExistingSheet() {
int dvRow = 0;
HSSFSheet sheet = wb.getSheetAt(0);
sheet.createRow(dvRow).createCell((short)0);
- HSSFDataValidation dv = new HSSFDataValidation((short)dvRow, (short)0, (short)dvRow, (short)0);
+ DVConstraint dc = DVConstraint.createNumericConstraint(VT.INTEGER, OP.EQUAL, "402", null);
+ HSSFDataValidation dv = new HSSFDataValidation(new CellRangeAddressList(dvRow, 0, dvRow, 0), dc);
+
- dv.setDataValidationType(HSSFDataValidation.DATA_TYPE_INTEGER);
dv.setEmptyCellAllowed(false);
- dv.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
- dv.setFirstFormula("42");
- dv.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
+ dv.setErrorStyle(ES.STOP);
dv.setShowPromptBox(true);
dv.createErrorBox("Error", "The value is wrong");
- dv.setSurppressDropDownArrow(true);
+ dv.setSuppressDropDownArrow(true);
+
+ // sheet.addValidationData(dv);
+
+
+ dc = DVConstraint.createNumericConstraint(VT.INTEGER, OP.EQUAL, "42", null);
+ dv = new HSSFDataValidation(new CellRangeAddressList(0, 0, 0, 0), dc);
+
+
+ dv.setEmptyCellAllowed(false);
+ dv.setErrorStyle(ES.STOP);
+ dv.setShowPromptBox(true);
+ dv.createErrorBox("Xxx", "Yyy");
+ dv.setSuppressDropDownArrow(true);
sheet.addValidationData(dv);
- wb.toString();
+
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
// and the DV records, Excel will not be able to open the workbook without error.
if (nextSid == 0x0867) {
- throw new AssertionFailedError("Identified bug 45519");
+ throw new AssertionFailedError("Identified bug XXXX");
}
assertEquals(DVRecord.sid, nextSid);
+
+
+
+ File tempDir = new File("c:/josh/temp");
+ File generatedFile = new File(tempDir, "dvEx2.xls");
+ try {
+ FileOutputStream fileOut = new FileOutputStream(generatedFile);
+ wb.write(fileOut);
+ fileOut.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
}
private int findIndex(byte[] largeData, byte[] searchPattern) {
byte firstByte = searchPattern[0];
* @author Alex Jacoby (ajacoby at gmail.com)
* @version %I%, %G%
*/
-public class TestHSSFDateUtil extends TestCase {
+public final class TestHSSFDateUtil extends TestCase {
public static final int CALENDAR_JANUARY = 0;
public static final int CALENDAR_FEBRUARY = 1;
public static final int CALENDAR_APRIL = 3;
public static final int CALENDAR_JULY = 6;
public static final int CALENDAR_OCTOBER = 9;
-
- public TestHSSFDateUtil(String s)
- {
- super(s);
- }
/**
* Checks the date conversion functions in the HSSFDateUtil class.
}
/**
- * Tests that we deal with timezones properly
+ * Tests that we deal with time-zones properly
*/
public void testCalendarConversion() {
GregorianCalendar date = new GregorianCalendar(2002, 0, 1, 12, 1, 1);
Date expected = date.getTime();
- double expectedExcel = HSSFDateUtil.getExcelDate(expected);
- // Iteratating over the hours exposes any rounding issues.
+ // Iterating over the hours exposes any rounding issues.
for (int hour = -12; hour <= 12; hour++)
{
String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00";
double excelDate = HSSFDateUtil.getExcelDate(date, false);
Date javaDate = HSSFDateUtil.getJavaDate(excelDate);
- // Should match despite timezone
+ // Should match despite time-zone
assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime());
}
}
assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), true), 0.00001);
}
- private Date createDate(int year, int month, int day) {
+ /**
+ * @param month zero based
+ * @param day one based
+ */
+ private static Date createDate(int year, int month, int day) {
Calendar c = new GregorianCalendar();
c.set(year, month, day, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
calendar = new GregorianCalendar(1901, 0, 1);
assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false));
}
+
+ public void testConvertTime() {
+
+ final double delta = 1E-7; // a couple of digits more accuracy than strictly required
+ assertEquals(0.5, HSSFDateUtil.convertTime("12:00"), delta);
+ assertEquals(2.0/3, HSSFDateUtil.convertTime("16:00"), delta);
+ assertEquals(0.0000116, HSSFDateUtil.convertTime("0:00:01"), delta);
+ assertEquals(0.7330440, HSSFDateUtil.convertTime("17:35:35"), delta);
+ }
- public static void main(String [] args) {
- System.out
- .println("Testing org.apache.poi.hssf.usermodel.TestHSSFDateUtil");
- junit.textui.TestRunner.run(TestHSSFDateUtil.class);
+ public void testParseDate() {
+ assertEquals(createDate(2008, Calendar.AUGUST, 3), HSSFDateUtil.parseYYYYMMDDDate("2008/08/03"));
+ assertEquals(createDate(1994, Calendar.MAY, 1), HSSFDateUtil.parseYYYYMMDDDate("1994/05/01"));
}
}