Extensive fixes for data validation (bug 44953)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@682225 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
29af743583
commit
8f5b968caf
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
<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="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">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>
|
<action dev="POI-DEVELOPERS" type="add">45466 - Partial support for removing excel comments (won't work for all excel versions yet)</action>
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
<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="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">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>
|
<action dev="POI-DEVELOPERS" type="add">45466 - Partial support for removing excel comments (won't work for all excel versions yet)</action>
|
||||||
|
@ -66,8 +66,11 @@ public final class FormulaParser {
|
|||||||
public static final int FORMULA_TYPE_CELL = 0;
|
public static final int FORMULA_TYPE_CELL = 0;
|
||||||
public static final int FORMULA_TYPE_SHARED = 1;
|
public static final int FORMULA_TYPE_SHARED = 1;
|
||||||
public static final int FORMULA_TYPE_ARRAY =2;
|
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;
|
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 String formulaString;
|
||||||
private final int formulaLength;
|
private final int formulaLength;
|
||||||
@ -75,12 +78,6 @@ public final class FormulaParser {
|
|||||||
|
|
||||||
private ParseNode _rootNode;
|
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';
|
private static char TAB = '\t';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,9 +109,13 @@ public final class FormulaParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Ptg[] parse(String formula, HSSFWorkbook book) {
|
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();
|
fp.parse();
|
||||||
return fp.getRPNPtg();
|
return fp.getRPNPtg(formulaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read New Character From Input Stream */
|
/** Read New Character From Input Stream */
|
||||||
|
@ -66,6 +66,9 @@ final class OperandClassTransformer {
|
|||||||
case FormulaParser.FORMULA_TYPE_CELL:
|
case FormulaParser.FORMULA_TYPE_CELL:
|
||||||
rootNodeOperandClass = Ptg.CLASS_VALUE;
|
rootNodeOperandClass = Ptg.CLASS_VALUE;
|
||||||
break;
|
break;
|
||||||
|
case FormulaParser.FORMULA_TYPE_DATAVALIDATION_LIST:
|
||||||
|
rootNodeOperandClass = Ptg.CLASS_REF;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Incomplete code - formula type ("
|
throw new RuntimeException("Incomplete code - formula type ("
|
||||||
+ _formulaType + ") not supported yet");
|
+ _formulaType + ") not supported yet");
|
||||||
|
@ -16,17 +16,14 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.record;
|
package org.apache.poi.hssf.record;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.apache.poi.hssf.record.UnicodeString.UnicodeRecordStats;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
import org.apache.poi.hssf.util.HSSFCellRangeAddress;
|
import org.apache.poi.hssf.usermodel.DVConstraint;
|
||||||
import org.apache.poi.hssf.util.HSSFCellRangeAddress.AddrStructure;
|
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.BitField;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.StringUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title: DATAVALIDATION Record (0x01BE)<p/>
|
* Title: DATAVALIDATION Record (0x01BE)<p/>
|
||||||
@ -35,336 +32,169 @@ import org.apache.poi.util.StringUtil;
|
|||||||
* are stored in a sequential list of DV records. This list is followed by
|
* are stored in a sequential list of DV records. This list is followed by
|
||||||
* DVAL record(s)
|
* DVAL record(s)
|
||||||
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
|
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
|
||||||
* @version 2.0-pre
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
public final class DVRecord extends Record
|
public final class DVRecord extends Record {
|
||||||
{
|
|
||||||
public final static short sid = 0x01BE;
|
public final static short sid = 0x01BE;
|
||||||
|
|
||||||
/**
|
/** the unicode string used for error/prompt title/text when not present */
|
||||||
* Option flags
|
private static final UnicodeString NULL_TEXT_STRING = new UnicodeString("\0");
|
||||||
*/
|
|
||||||
private int field_option_flags;
|
|
||||||
|
|
||||||
/**
|
/** Option flags */
|
||||||
* Title of the prompt box
|
private int _option_flags;
|
||||||
*/
|
/** Title of the prompt box */
|
||||||
private String field_title_prompt;
|
private UnicodeString _promptTitle;
|
||||||
|
/** Title of the error box */
|
||||||
/**
|
private UnicodeString _errorTitle;
|
||||||
* Title of the error box
|
/** Text of the prompt box */
|
||||||
*/
|
private UnicodeString _promptText;
|
||||||
private String field_title_error;
|
/** Text of the error box */
|
||||||
|
private UnicodeString _errorText;
|
||||||
/**
|
/** Not used - Excel seems to always write 0x3FE0 */
|
||||||
* Text of the prompt box
|
private short _not_used_1 = 0x3FE0;
|
||||||
*/
|
/** Formula data for first condition (RPN token array without size field) */
|
||||||
private String field_text_prompt;
|
private Ptg[] _formula1;
|
||||||
|
/** Not used - Excel seems to always write 0x0000 */
|
||||||
/**
|
private short _not_used_2 = 0x0000;
|
||||||
* Text of the error box
|
/** Formula data for second condition (RPN token array without size field) */
|
||||||
*/
|
private Ptg[] _formula2;
|
||||||
private String field_text_error;
|
/** Cell range address list with all affected ranges */
|
||||||
|
private CellRangeAddressList _regions;
|
||||||
/**
|
|
||||||
* 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
|
* Option flags field
|
||||||
|
*
|
||||||
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
|
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
|
||||||
*/
|
*/
|
||||||
private BitField opt_data_type = new BitField(0x0000000F);
|
private static final BitField opt_data_type = new BitField(0x0000000F);
|
||||||
private BitField opt_error_style = new BitField(0x00000070);
|
private static final BitField opt_error_style = new BitField(0x00000070);
|
||||||
private BitField opt_string_list_formula = new BitField(0x00000080);
|
private static final BitField opt_string_list_formula = new BitField(0x00000080);
|
||||||
private BitField opt_empty_cell_allowed = new BitField(0x00000100);
|
private static final BitField opt_empty_cell_allowed = new BitField(0x00000100);
|
||||||
private BitField opt_suppress_dropdown_arrow = new BitField(0x00000200);
|
private static final BitField opt_suppress_dropdown_arrow = new BitField(0x00000200);
|
||||||
private BitField opt_show_prompt_on_cell_selected = new BitField(0x00040000);
|
private static final BitField opt_show_prompt_on_cell_selected = new BitField(0x00040000);
|
||||||
private BitField opt_show_error_on_invalid_value = new BitField(0x00080000);
|
private static final BitField opt_show_error_on_invalid_value = new BitField(0x00080000);
|
||||||
private BitField opt_condition_operator = new BitField(0x00F00000);
|
private static final BitField opt_condition_operator = new BitField(0x00700000);
|
||||||
|
|
||||||
public DVRecord()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a DV record and sets its fields appropriately.
|
* Constructs a DV record and sets its fields appropriately.
|
||||||
*
|
*
|
||||||
* @param in the RecordInputstream to read the record from
|
* @param in the RecordInputstream to read the record from
|
||||||
*/
|
*/
|
||||||
|
public DVRecord(RecordInputStream in) {
|
||||||
public DVRecord(RecordInputStream in)
|
|
||||||
{
|
|
||||||
super(in);
|
super(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void validateSid(short id)
|
public DVRecord(int validationType, int operator, int errorStyle, boolean emptyCellAllowed,
|
||||||
{
|
boolean suppressDropDownArrow, boolean isExplicitList,
|
||||||
if (id != sid)
|
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");
|
throw new RecordFormatException("NOT a valid DV RECORD");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fillFields(RecordInputStream in)
|
protected void fillFields(RecordInputStream in) {
|
||||||
{
|
|
||||||
field_rpn_token_1 = new Stack();
|
|
||||||
field_rpn_token_2 = new Stack();
|
|
||||||
|
|
||||||
this.field_option_flags = in.readInt();
|
_option_flags = in.readInt();
|
||||||
this._hash_strings = new Hashtable(4);
|
|
||||||
|
|
||||||
StringHandler strHandler_prompt_title = new StringHandler( in );
|
_promptTitle = readUnicodeString(in);
|
||||||
this.field_title_prompt = strHandler_prompt_title.getStringData();
|
_errorTitle = readUnicodeString(in);
|
||||||
this._hash_strings.put(DVRecord.STRING_PROMPT_TITLE, strHandler_prompt_title);
|
_promptText = readUnicodeString(in);
|
||||||
|
_errorText = readUnicodeString(in);
|
||||||
|
|
||||||
StringHandler strHandler_error_title = new StringHandler( in );
|
int field_size_first_formula = in.readUShort();
|
||||||
this.field_title_error = strHandler_error_title.getStringData();
|
_not_used_1 = in.readShort();
|
||||||
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
|
//read first formula data condition
|
||||||
int token_pos = 0;
|
_formula1 = Ptg.readTokens(field_size_first_formula, in);
|
||||||
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();
|
int field_size_sec_formula = in.readUShort();
|
||||||
this.field_not_used_2 = in.readShort();
|
_not_used_2 = in.readShort();
|
||||||
|
|
||||||
//read sec formula data condition
|
//read sec formula data condition
|
||||||
if (false) { // TODO - prior to bug 44710 this 'skip' was being executed. write a junit to confirm this fix
|
_formula2 = Ptg.readTokens(field_size_sec_formula, in);
|
||||||
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
|
//read cell range address list with all affected ranges
|
||||||
this.field_regions = new HSSFCellRangeAddress(in);
|
_regions = new CellRangeAddressList(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --> start option flags
|
// --> 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
|
* @return the condition data type
|
||||||
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
|
* @see DVConstraint.ValidationType
|
||||||
*/
|
*/
|
||||||
public int getDataType()
|
public int getDataType() {
|
||||||
{
|
return opt_data_type.getValue(_option_flags);
|
||||||
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
|
* @return the condition error style
|
||||||
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
|
* @see HSSFDataValidation.ErrorStyle
|
||||||
*/
|
*/
|
||||||
public int getErrorStyle()
|
public int getErrorStyle() {
|
||||||
{
|
return opt_error_style.getValue(_option_flags);
|
||||||
return this.opt_error_style.getValue(this.field_option_flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set if in list validations the string list is explicitly given in the formula
|
* @return <code>true</code> if in list validations the string list is explicitly given in the
|
||||||
* @param type - true if in list validations the string list is explicitly given in the formula; false otherwise
|
* formula, <code>false</code> otherwise
|
||||||
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
|
|
||||||
*/
|
*/
|
||||||
public void setListExplicitFormula(boolean explicit)
|
public boolean getListExplicitFormula() {
|
||||||
{
|
return (opt_string_list_formula.isSet(_option_flags));
|
||||||
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 <code>true</code> if empty values are allowed in cells, <code>false</code> 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()
|
public boolean getEmptyCellAllowed() {
|
||||||
{
|
return (opt_empty_cell_allowed.isSet(_option_flags));
|
||||||
return (this.opt_string_list_formula.isSet(this.field_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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set if empty values are allowed in cells
|
* @return <code>true</code> if a prompt window should appear when cell is selected, <code>false</code> otherwise
|
||||||
* @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)
|
public boolean getShowPromptOnCellSelected() {
|
||||||
{
|
return (opt_show_prompt_on_cell_selected.isSet(_option_flags));
|
||||||
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 <code>true</code> if an error window should appear when an invalid value is entered
|
||||||
* @return if empty values are allowed in cells, false otherwise
|
* in the cell, <code>false</code> otherwise
|
||||||
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
|
|
||||||
*/
|
*/
|
||||||
public boolean getEmptyCellAllowed()
|
public boolean getShowErrorOnInvalidValue() {
|
||||||
{
|
return (opt_show_error_on_invalid_value.isSet(_option_flags));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -372,93 +202,37 @@ public final class DVRecord extends Record
|
|||||||
* @return the condition operator
|
* @return the condition operator
|
||||||
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
|
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
|
||||||
*/
|
*/
|
||||||
public int getConditionOperator()
|
public int getConditionOperator() {
|
||||||
{
|
return opt_condition_operator.getValue(_option_flags);
|
||||||
return this.opt_condition_operator.getValue(this.field_option_flags);
|
|
||||||
}
|
}
|
||||||
// <-- end option flags
|
// <-- end option flags
|
||||||
|
|
||||||
public void setFirstFormulaRPN( Stack rpn )
|
|
||||||
{
|
|
||||||
this.field_rpn_token_1 = rpn;
|
|
||||||
|
public CellRangeAddressList getCellRangeAddress() {
|
||||||
|
return this._regions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFirstFormulaSize( short size )
|
|
||||||
{
|
|
||||||
this.field_size_first_formula = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSecFormulaRPN( Stack rpn )
|
public String toString() {
|
||||||
{
|
|
||||||
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();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append("[DV]\n");
|
sb.append("[DV]\n");
|
||||||
sb.append(" options=").append(Integer.toHexString(field_option_flags));
|
sb.append(" options=").append(Integer.toHexString(_option_flags));
|
||||||
sb.append(" title-prompt=").append(field_title_prompt);
|
sb.append(" title-prompt=").append(formatTextTitle(_promptTitle));
|
||||||
sb.append(" title-error=").append(field_title_error);
|
sb.append(" title-error=").append(formatTextTitle(_errorTitle));
|
||||||
sb.append(" text-prompt=").append(field_text_prompt);
|
sb.append(" text-prompt=").append(formatTextTitle(_promptText));
|
||||||
sb.append(" text-error=").append(field_text_error);
|
sb.append(" text-error=").append(formatTextTitle(_errorText));
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
appendFormula(sb, "Formula 1:", field_rpn_token_1);
|
appendFormula(sb, "Formula 1:", _formula1);
|
||||||
appendFormula(sb, "Formula 2:", field_rpn_token_2);
|
appendFormula(sb, "Formula 2:", _formula2);
|
||||||
int nRegions = field_regions.getADDRStructureNumber();
|
sb.append("Regions: ");
|
||||||
|
int nRegions = _regions.getADDRStructureNumber();
|
||||||
for(int i=0; i<nRegions; i++) {
|
for(int i=0; i<nRegions; i++) {
|
||||||
AddrStructure addr = field_regions.getADDRStructureAt(i);
|
if (i>0) {
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
CellRangeAddress addr = _regions.getCellRangeAddress(i);
|
||||||
sb.append('(').append(addr.getFirstRow()).append(',').append(addr.getLastRow());
|
sb.append('(').append(addr.getFirstRow()).append(',').append(addr.getLastRow());
|
||||||
sb.append(',').append(addr.getFirstColumn()).append(',').append(addr.getLastColumn()).append(')');
|
sb.append(',').append(addr.getFirstColumn()).append(',').append(addr.getLastColumn()).append(')');
|
||||||
}
|
}
|
||||||
@ -468,81 +242,95 @@ public final class DVRecord extends Record
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendFormula(StringBuffer sb, String label, Stack stack) {
|
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);
|
sb.append(label);
|
||||||
if (stack.isEmpty()) {
|
if (ptgs.length < 1) {
|
||||||
sb.append("<empty>\n");
|
sb.append("<empty>\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
Ptg[] ptgs = new Ptg[stack.size()];
|
|
||||||
stack.toArray(ptgs);
|
|
||||||
for (int i = 0; i < ptgs.length; i++) {
|
for (int i = 0; i < ptgs.length; i++) {
|
||||||
sb.append('\t').append(ptgs[i].toString()).append('\n');
|
sb.append('\t').append(ptgs[i].toString()).append('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int serialize(int offset, byte [] data)
|
public int serialize(int offset, byte [] data) {
|
||||||
{
|
|
||||||
int size = this.getRecordSize();
|
int size = this.getRecordSize();
|
||||||
LittleEndian.putShort(data, 0 + offset, sid);
|
LittleEndian.putShort(data, 0 + offset, sid);
|
||||||
LittleEndian.putShort(data, 2 + offset, ( short ) (size-4));
|
LittleEndian.putShort(data, 2 + offset, ( short ) (size-4));
|
||||||
|
|
||||||
int pos = 4;
|
int pos = 4;
|
||||||
LittleEndian.putInt(data, pos + offset, this.getOptionFlags());
|
LittleEndian.putInt(data, pos + offset, _option_flags);
|
||||||
pos += 4;
|
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 += serializeUnicodeString(_promptTitle, pos+offset, data);
|
||||||
pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_PROMPT_TEXT )).serialize(pos+offset, data);
|
pos += serializeUnicodeString(_errorTitle, pos+offset, data);
|
||||||
pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_ERROR_TEXT )).serialize(pos+offset, data);
|
pos += serializeUnicodeString(_promptText, pos+offset, data);
|
||||||
LittleEndian.putShort(data, offset+pos, this.field_size_first_formula);
|
pos += serializeUnicodeString(_errorText, pos+offset, data);
|
||||||
|
LittleEndian.putUShort(data, offset+pos, Ptg.getEncodedSize(_formula1));
|
||||||
pos += 2;
|
pos += 2;
|
||||||
LittleEndian.putShort(data, offset+pos, this.field_not_used_1);
|
LittleEndian.putUShort(data, offset+pos, _not_used_1);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
for (int k = 0; k < this.field_rpn_token_1.size(); k++)
|
pos += Ptg.serializePtgs(_formula1, data, pos+offset);
|
||||||
{
|
|
||||||
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);
|
LittleEndian.putUShort(data, offset+pos, Ptg.getEncodedSize(_formula2));
|
||||||
pos += 2;
|
pos += 2;
|
||||||
LittleEndian.putShort(data, offset+pos, this.field_not_used_2);
|
LittleEndian.putShort(data, offset+pos, _not_used_2);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
if ( this.field_size_sec_formula > 0 )
|
pos += Ptg.serializePtgs(_formula2, data, pos+offset);
|
||||||
{
|
_regions.serialize(pos+offset, data);
|
||||||
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;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRecordSize()
|
/**
|
||||||
{
|
* 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;
|
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 )
|
size += getUnicodeStringSize(_promptTitle);
|
||||||
{
|
size += getUnicodeStringSize(_errorTitle);
|
||||||
Enumeration enum_keys = this._hash_strings.keys();
|
size += getUnicodeStringSize(_promptText);
|
||||||
while ( enum_keys.hasMoreElements() )
|
size += getUnicodeStringSize(_errorText);
|
||||||
{
|
size += Ptg.getEncodedSize(_formula1);
|
||||||
size += ((StringHandler)this._hash_strings.get( (Integer)enum_keys.nextElement() )).getSize();
|
size += Ptg.getEncodedSize(_formula2);
|
||||||
}
|
size += _regions.getSize();
|
||||||
}
|
|
||||||
size += this.field_size_first_formula+ this.field_size_sec_formula;
|
|
||||||
size += this.field_regions.getSize();
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getSid()
|
public short getSid() {
|
||||||
{
|
return sid;
|
||||||
return this.sid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -552,89 +340,4 @@ public final class DVRecord extends Record
|
|||||||
public Object clone() {
|
public Object clone() {
|
||||||
return cloneViaReserialise();
|
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,7 @@ package org.apache.poi.hssf.record.aggregates;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.model.FormulaParser;
|
|
||||||
import org.apache.poi.hssf.model.RecordStream;
|
import org.apache.poi.hssf.model.RecordStream;
|
||||||
import org.apache.poi.hssf.record.CFHeaderRecord;
|
import org.apache.poi.hssf.record.CFHeaderRecord;
|
||||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||||
@ -34,10 +32,6 @@ import org.apache.poi.hssf.record.PaneRecord;
|
|||||||
import org.apache.poi.hssf.record.Record;
|
import org.apache.poi.hssf.record.Record;
|
||||||
import org.apache.poi.hssf.record.SelectionRecord;
|
import org.apache.poi.hssf.record.SelectionRecord;
|
||||||
import org.apache.poi.hssf.record.WindowTwoRecord;
|
import org.apache.poi.hssf.record.WindowTwoRecord;
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|
||||||
import org.apache.poi.hssf.util.HSSFCellRangeAddress;
|
|
||||||
import org.apache.poi.hssf.util.HSSFDataValidation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the DVALRecord and DVRecords for a single sheet<br/>
|
* Manages the DVALRecord and DVRecords for a single sheet<br/>
|
||||||
@ -177,63 +171,7 @@ public final class DataValidityTable extends RecordAggregate {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDataValidation(HSSFDataValidation dataValidation, HSSFWorkbook workbook) {
|
public void addDataValidation(DVRecord dvRecord) {
|
||||||
|
|
||||||
DVRecord dvRecord = new DVRecord();
|
|
||||||
|
|
||||||
// dv record's option flags
|
|
||||||
dvRecord.setDataType(dataValidation.getDataValidationType());
|
|
||||||
dvRecord.setErrorStyle(dataValidation.getErrorStyle());
|
|
||||||
dvRecord.setEmptyCellAllowed(dataValidation.getEmptyCellAllowed());
|
|
||||||
dvRecord.setSuppressDropdownArrow(dataValidation.getSuppressDropDownArrow());
|
|
||||||
dvRecord.setShowPromptOnCellSelected(dataValidation.getShowPromptBox());
|
|
||||||
dvRecord.setShowErrorOnInvalidValue(dataValidation.getShowErrorBox());
|
|
||||||
dvRecord.setConditionOperator(dataValidation.getOperator());
|
|
||||||
|
|
||||||
// string fields
|
|
||||||
dvRecord.setStringField(DVRecord.STRING_PROMPT_TITLE, dataValidation.getPromptBoxTitle());
|
|
||||||
dvRecord.setStringField(DVRecord.STRING_PROMPT_TEXT, dataValidation.getPromptBoxText());
|
|
||||||
dvRecord.setStringField(DVRecord.STRING_ERROR_TITLE, dataValidation.getErrorBoxTitle());
|
|
||||||
dvRecord.setStringField(DVRecord.STRING_ERROR_TEXT, dataValidation.getErrorBoxText());
|
|
||||||
|
|
||||||
// formula fields ( size and data )
|
|
||||||
Stack ptg_arr = new Stack();
|
|
||||||
Ptg[] ptg = FormulaParser.parse(dataValidation.getFirstFormula(), workbook);
|
|
||||||
int size = 0;
|
|
||||||
for (int k = 0; k < ptg.length; k++) {
|
|
||||||
if (ptg[k] instanceof org.apache.poi.hssf.record.formula.AreaPtg) {
|
|
||||||
// we should set ptgClass to Ptg.CLASS_REF and explicit formula
|
|
||||||
// string to false
|
|
||||||
// ptg[k].setClass(Ptg.CLASS_REF);
|
|
||||||
// obj_validation.setExplicitListFormula(false);
|
|
||||||
}
|
|
||||||
size += ptg[k].getSize();
|
|
||||||
ptg_arr.push(ptg[k]);
|
|
||||||
}
|
|
||||||
dvRecord.setFirstFormulaRPN(ptg_arr);
|
|
||||||
dvRecord.setFirstFormulaSize((short) size);
|
|
||||||
|
|
||||||
dvRecord.setListExplicitFormula(dataValidation.getExplicitListFormula());
|
|
||||||
|
|
||||||
if (dataValidation.getSecondFormula() != null) {
|
|
||||||
|
|
||||||
ptg_arr = new Stack();
|
|
||||||
ptg = FormulaParser.parse(dataValidation.getSecondFormula(), workbook);
|
|
||||||
size = 0;
|
|
||||||
for (int k = 0; k < ptg.length; k++) {
|
|
||||||
size += ptg[k].getSize();
|
|
||||||
ptg_arr.push(ptg[k]);
|
|
||||||
}
|
|
||||||
dvRecord.setSecFormulaRPN(ptg_arr);
|
|
||||||
dvRecord.setSecFormulaSize((short) size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// dv records cell range field
|
|
||||||
HSSFCellRangeAddress cell_range = new HSSFCellRangeAddress();
|
|
||||||
cell_range.addADDRStructure(dataValidation.getFirstRow(), dataValidation.getFirstColumn(),
|
|
||||||
dataValidation.getLastRow(), dataValidation.getLastColumn());
|
|
||||||
dvRecord.setCellRangeAddress(cell_range);
|
|
||||||
|
|
||||||
_validationList.add(dvRecord);
|
_validationList.add(dvRecord);
|
||||||
_headerRec.setDVRecNo(_validationList.size());
|
_headerRec.setDVRecNo(_validationList.size());
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public final class NumberPtg extends ScalarConstantPtg {
|
|||||||
/** Create a NumberPtg from a byte array read from disk */
|
/** Create a NumberPtg from a byte array read from disk */
|
||||||
public NumberPtg(RecordInputStream in)
|
public NumberPtg(RecordInputStream in)
|
||||||
{
|
{
|
||||||
field_1_value = in.readDouble();
|
this(in.readDouble());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create a NumberPtg from a string representation of the number
|
/** Create a NumberPtg from a string representation of the number
|
||||||
@ -45,9 +45,12 @@ public final class NumberPtg extends ScalarConstantPtg {
|
|||||||
* @param value : String representation of a floating point number
|
* @param value : String representation of a floating point number
|
||||||
*/
|
*/
|
||||||
public NumberPtg(String value) {
|
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 double getValue()
|
||||||
{
|
{
|
||||||
@ -67,6 +70,15 @@ public final class NumberPtg extends ScalarConstantPtg {
|
|||||||
|
|
||||||
public String toFormulaString(HSSFWorkbook book)
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|||||||
* @author Jason Height (jheight at chariot dot net dot au)
|
* @author Jason Height (jheight at chariot dot net dot au)
|
||||||
*/
|
*/
|
||||||
public abstract class Ptg implements Cloneable {
|
public abstract class Ptg implements Cloneable {
|
||||||
|
public static final Ptg[] EMPTY_PTG_ARRAY = { };
|
||||||
|
|
||||||
/* convert infix order ptg list to rpn order ptg list
|
/* convert infix order ptg list to rpn order ptg list
|
||||||
* @return List ptgs in RPN order
|
* @return List ptgs in RPN order
|
||||||
@ -250,6 +251,9 @@ public abstract class Ptg implements Cloneable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static Ptg[] toPtgArray(List l) {
|
private static Ptg[] toPtgArray(List l) {
|
||||||
|
if (l.isEmpty()) {
|
||||||
|
return EMPTY_PTG_ARRAY;
|
||||||
|
}
|
||||||
Ptg[] result = new Ptg[l.size()];
|
Ptg[] result = new Ptg[l.size()];
|
||||||
l.toArray(result);
|
l.toArray(result);
|
||||||
return result;
|
return result;
|
||||||
|
479
src/java/org/apache/poi/hssf/usermodel/DVConstraint.java
Normal file
479
src/java/org/apache/poi/hssf/usermodel/DVConstraint.java
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
235
src/java/org/apache/poi/hssf/usermodel/HSSFDataValidation.java
Normal file
235
src/java/org/apache/poi/hssf/usermodel/HSSFDataValidation.java
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -16,17 +16,12 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DateUtil.java
|
|
||||||
*
|
|
||||||
* Created on January 19, 2002, 9:30 AM
|
|
||||||
*/
|
|
||||||
package org.apache.poi.hssf.usermodel;
|
package org.apache.poi.hssf.usermodel;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains methods for dealing with Excel dates.
|
* Contains methods for dealing with Excel dates.
|
||||||
@ -38,16 +33,19 @@ import java.util.GregorianCalendar;
|
|||||||
* @author Alex Jacoby (ajacoby at gmail.com)
|
* @author Alex Jacoby (ajacoby at gmail.com)
|
||||||
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
|
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
|
||||||
*/
|
*/
|
||||||
|
public final class HSSFDateUtil {
|
||||||
public class HSSFDateUtil
|
private HSSFDateUtil() {
|
||||||
{
|
// no instances of this class
|
||||||
private HSSFDateUtil()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
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 =
|
private static final int BAD_DATE = -1; // used to specify that date is invalid
|
||||||
-1; // used to specify that date is invalid
|
private static final long DAY_MILLISECONDS = SECONDS_PER_DAY * 1000L;
|
||||||
private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
|
|
||||||
|
private static final Pattern TIME_SEPARATOR_PATTERN = Pattern.compile(":");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a Date, converts it into a double representing its internal Excel representation,
|
* Given a Date, converts it into a double representing its internal Excel representation,
|
||||||
@ -91,7 +89,7 @@ public class HSSFDateUtil
|
|||||||
(use1904windowing && date.get(Calendar.YEAR) < 1904))
|
(use1904windowing && date.get(Calendar.YEAR) < 1904))
|
||||||
{
|
{
|
||||||
return BAD_DATE;
|
return BAD_DATE;
|
||||||
} else {
|
}
|
||||||
// Because of daylight time saving we cannot use
|
// Because of daylight time saving we cannot use
|
||||||
// date.getTime() - calStart.getTimeInMillis()
|
// date.getTime() - calStart.getTimeInMillis()
|
||||||
// as the difference in milliseconds between 00:00 and 04:00
|
// as the difference in milliseconds between 00:00 and 04:00
|
||||||
@ -116,7 +114,6 @@ public class HSSFDateUtil
|
|||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an Excel date with using 1900 date windowing, and
|
* Given an Excel date with using 1900 date windowing, and
|
||||||
@ -158,7 +155,9 @@ public class HSSFDateUtil
|
|||||||
* @see java.util.TimeZone
|
* @see java.util.TimeZone
|
||||||
*/
|
*/
|
||||||
public static Date getJavaDate(double date, boolean use1904windowing) {
|
public static Date getJavaDate(double date, boolean use1904windowing) {
|
||||||
if (isValidExcelDate(date)) {
|
if (!isValidExcelDate(date)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
int startYear = 1900;
|
int startYear = 1900;
|
||||||
int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
|
int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
|
||||||
int wholeDays = (int)Math.floor(date);
|
int wholeDays = (int)Math.floor(date);
|
||||||
@ -178,10 +177,6 @@ public class HSSFDateUtil
|
|||||||
calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
|
calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
|
||||||
return calendar.getTime();
|
return calendar.getTime();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a format ID and its format String, will check to see if the
|
* Given a format ID and its format String, will check to see if the
|
||||||
@ -244,8 +239,6 @@ public class HSSFDateUtil
|
|||||||
* @see #isADateFormat(int, java.lang.String)
|
* @see #isADateFormat(int, java.lang.String)
|
||||||
*/
|
*/
|
||||||
public static boolean isInternalDateFormat(int format) {
|
public static boolean isInternalDateFormat(int format) {
|
||||||
boolean retval =false;
|
|
||||||
|
|
||||||
switch(format) {
|
switch(format) {
|
||||||
// Internal Date Formats as described on page 427 in
|
// Internal Date Formats as described on page 427 in
|
||||||
// Microsoft Excel Dev's Kit...
|
// Microsoft Excel Dev's Kit...
|
||||||
@ -261,14 +254,9 @@ public class HSSFDateUtil
|
|||||||
case 0x2d:
|
case 0x2d:
|
||||||
case 0x2e:
|
case 0x2e:
|
||||||
case 0x2f:
|
case 0x2f:
|
||||||
retval = true;
|
return true;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
retval = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return retval;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -377,5 +365,95 @@ public class HSSFDateUtil
|
|||||||
return 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ import org.apache.poi.hssf.record.*;
|
|||||||
import org.apache.poi.hssf.record.aggregates.DataValidityTable;
|
import org.apache.poi.hssf.record.aggregates.DataValidityTable;
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
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.PaneInformation;
|
||||||
import org.apache.poi.hssf.util.Region;
|
import org.apache.poi.hssf.util.Region;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
@ -382,7 +381,8 @@ public final class HSSFSheet {
|
|||||||
}
|
}
|
||||||
DataValidityTable dvt = sheet.getOrCreateDataValidityTable();
|
DataValidityTable dvt = sheet.getOrCreateDataValidityTable();
|
||||||
|
|
||||||
dvt.addDataValidation(dataValidation, workbook);
|
DVRecord dvRecord = dataValidation.createDVRecord(workbook);
|
||||||
|
dvt.addDataValidation(dvRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
130
src/java/org/apache/poi/hssf/util/CellRangeAddress.java
Normal file
130
src/java/org/apache/poi/hssf/util/CellRangeAddress.java
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'
|
||||||
|
*
|
||||||
|
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
|
||||||
|
*/
|
||||||
|
public final class CellRangeAddress {
|
||||||
|
private static final int ENCODED_SIZE = 8;
|
||||||
|
|
||||||
|
private int _firstRow;
|
||||||
|
private int _firstCol;
|
||||||
|
private int _lastRow;
|
||||||
|
private int _lastCol;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO - replace other incarnations of 'Cell Range Address' throughout POI:
|
||||||
|
* org.apache.poi.hssf.util.CellRange
|
||||||
|
* org.apache.poi.hssf.record.cf.CellRange
|
||||||
|
* org.apache.poi.hssf.util.HSSFCellRangeAddress.AddrStructure
|
||||||
|
* org.apache.poi.hssf.record.MergeCellsRecord.MergedRegion
|
||||||
|
* org.apache.poi.hssf.record.SelectionRecord.Reference
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||||
|
_firstRow = firstRow;
|
||||||
|
_lastRow = lastRow;
|
||||||
|
_firstCol = firstCol;
|
||||||
|
_lastCol = lastCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CellRangeAddress(RecordInputStream in) {
|
||||||
|
if (in.remaining() < ENCODED_SIZE) {
|
||||||
|
// Ran out of data
|
||||||
|
throw new RuntimeException("Ran out of data reading CellRangeAddress");
|
||||||
|
}
|
||||||
|
_firstRow = in.readUShort();
|
||||||
|
_lastRow = in.readUShort();
|
||||||
|
_firstCol = in.readUShort();
|
||||||
|
_lastCol = in.readUShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return column number for the upper left hand corner
|
||||||
|
*/
|
||||||
|
public int getFirstColumn() {
|
||||||
|
return _firstCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return row number for the upper left hand corner
|
||||||
|
*/
|
||||||
|
public int getFirstRow() {
|
||||||
|
return _firstRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return column number for the lower right hand corner
|
||||||
|
*/
|
||||||
|
public int getLastColumn() {
|
||||||
|
return _lastCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return row number for the lower right hand corner
|
||||||
|
*/
|
||||||
|
public int getLastRow() {
|
||||||
|
return _lastRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param _firstCol column number for the upper left hand corner
|
||||||
|
*/
|
||||||
|
public void setFirstColumn(int firstCol) {
|
||||||
|
_firstCol = firstCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param rowFrom row number for the upper left hand corner
|
||||||
|
*/
|
||||||
|
public void setFirstRow(int firstRow) {
|
||||||
|
_firstRow = firstRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param colTo column number for the lower right hand corner
|
||||||
|
*/
|
||||||
|
public void setLastColumn(int lastCol) {
|
||||||
|
_lastCol = lastCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param rowTo row number for the lower right hand corner
|
||||||
|
*/
|
||||||
|
public void setLastRow(int lastRow) {
|
||||||
|
_lastRow = lastRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ int serialize(byte[] data, int offset) {
|
||||||
|
LittleEndian.putUShort(data, offset + 0, _firstRow);
|
||||||
|
LittleEndian.putUShort(data, offset + 2, _lastRow);
|
||||||
|
LittleEndian.putUShort(data, offset + 4, _firstCol);
|
||||||
|
LittleEndian.putUShort(data, offset + 6, _lastCol);
|
||||||
|
return ENCODED_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getEncodedSize(int numberOfItems) {
|
||||||
|
return numberOfItems * ENCODED_SIZE;
|
||||||
|
}
|
||||||
|
}
|
117
src/java/org/apache/poi/hssf/util/CellRangeAddressList.java
Normal file
117
src/java/org/apache/poi/hssf/util/CellRangeAddressList.java
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
@ -1,269 +0,0 @@
|
|||||||
/* ====================================================================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,483 +0,0 @@
|
|||||||
/* ====================================================================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -39,7 +39,7 @@ import org.apache.poi.hssf.model.Workbook;
|
|||||||
* @author Alex Jacoby (ajacoby at gmail.com)
|
* @author Alex Jacoby (ajacoby at gmail.com)
|
||||||
* @version %I%, %G%
|
* @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_JANUARY = 0;
|
||||||
public static final int CALENDAR_FEBRUARY = 1;
|
public static final int CALENDAR_FEBRUARY = 1;
|
||||||
@ -48,11 +48,6 @@ public class TestHSSFDateUtil extends TestCase {
|
|||||||
public static final int CALENDAR_JULY = 6;
|
public static final int CALENDAR_JULY = 6;
|
||||||
public static final int CALENDAR_OCTOBER = 9;
|
public static final int CALENDAR_OCTOBER = 9;
|
||||||
|
|
||||||
public TestHSSFDateUtil(String s)
|
|
||||||
{
|
|
||||||
super(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the date conversion functions in the HSSFDateUtil class.
|
* Checks the date conversion functions in the HSSFDateUtil class.
|
||||||
*/
|
*/
|
||||||
@ -193,14 +188,13 @@ public class TestHSSFDateUtil extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that we deal with timezones properly
|
* Tests that we deal with time-zones properly
|
||||||
*/
|
*/
|
||||||
public void testCalendarConversion() {
|
public void testCalendarConversion() {
|
||||||
GregorianCalendar date = new GregorianCalendar(2002, 0, 1, 12, 1, 1);
|
GregorianCalendar date = new GregorianCalendar(2002, 0, 1, 12, 1, 1);
|
||||||
Date expected = date.getTime();
|
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++)
|
for (int hour = -12; hour <= 12; hour++)
|
||||||
{
|
{
|
||||||
String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00";
|
String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00";
|
||||||
@ -209,7 +203,7 @@ public class TestHSSFDateUtil extends TestCase {
|
|||||||
double excelDate = HSSFDateUtil.getExcelDate(date, false);
|
double excelDate = HSSFDateUtil.getExcelDate(date, false);
|
||||||
Date javaDate = HSSFDateUtil.getJavaDate(excelDate);
|
Date javaDate = HSSFDateUtil.getJavaDate(excelDate);
|
||||||
|
|
||||||
// Should match despite timezone
|
// Should match despite time-zone
|
||||||
assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime());
|
assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,7 +396,11 @@ public class TestHSSFDateUtil extends TestCase {
|
|||||||
assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), true), 0.00001);
|
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();
|
Calendar c = new GregorianCalendar();
|
||||||
c.set(year, month, day, 0, 0, 0);
|
c.set(year, month, day, 0, 0, 0);
|
||||||
c.set(Calendar.MILLISECOND, 0);
|
c.set(Calendar.MILLISECOND, 0);
|
||||||
@ -421,9 +419,17 @@ public class TestHSSFDateUtil extends TestCase {
|
|||||||
assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false));
|
assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String [] args) {
|
public void testConvertTime() {
|
||||||
System.out
|
|
||||||
.println("Testing org.apache.poi.hssf.usermodel.TestHSSFDateUtil");
|
final double delta = 1E-7; // a couple of digits more accuracy than strictly required
|
||||||
junit.textui.TestRunner.run(TestHSSFDateUtil.class);
|
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 void testParseDate() {
|
||||||
|
assertEquals(createDate(2008, Calendar.AUGUST, 3), HSSFDateUtil.parseYYYYMMDDDate("2008/08/03"));
|
||||||
|
assertEquals(createDate(1994, Calendar.MAY, 1), HSSFDateUtil.parseYYYYMMDDDate("1994/05/01"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user