diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml
index 3660da72e4..77f9608e60 100644
--- a/src/documentation/content/xdocs/changes.xml
+++ b/src/documentation/content/xdocs/changes.xml
@@ -37,6 +37,7 @@
true
if in list validations the string list is explicitly given in the
+ * formula, false
otherwise
+ */
+ public boolean getListExplicitFormula() {
+ return (opt_string_list_formula.isSet(_option_flags));
+ }
+
+ /**
+ * @return true
if empty values are allowed in cells, false
otherwise
+ */
+ public boolean getEmptyCellAllowed() {
+ return (opt_empty_cell_allowed.isSet(_option_flags));
+ }
+
+
+ /**
+ * @return true
if drop down arrow should be suppressed when list validation is
+ * used, false
otherwise
+ */
+ public boolean getSuppressDropdownArrow() {
+ return (opt_suppress_dropdown_arrow.isSet(_option_flags));
+ }
+
+ /**
+ * @return true
if a prompt window should appear when cell is selected, false
otherwise
+ */
+ public boolean getShowPromptOnCellSelected() {
+ return (opt_show_prompt_on_cell_selected.isSet(_option_flags));
+ }
+
+ /**
+ * @return true
if an error window should appear when an invalid value is entered
+ * in the cell, false
otherwise
+ */
+ public boolean getShowErrorOnInvalidValue() {
+ return (opt_show_error_on_invalid_value.isSet(_option_flags));
+ }
+
+ /**
+ * get the condition operator
+ * @return the condition operator
+ * @see org.apache.poi.hssf.util.HSSFDataValidation utility class
+ */
+ public int getConditionOperator() {
+ return opt_condition_operator.getValue(_option_flags);
+ }
+ // <-- end option flags
+
+
+
+
+ public CellRangeAddressList getCellRangeAddress() {
+ return this._regions;
+ }
+
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[DV]\n");
+ sb.append(" options=").append(Integer.toHexString(_option_flags));
+ sb.append(" title-prompt=").append(formatTextTitle(_promptTitle));
+ sb.append(" title-error=").append(formatTextTitle(_errorTitle));
+ sb.append(" text-prompt=").append(formatTextTitle(_promptText));
+ sb.append(" text-error=").append(formatTextTitle(_errorText));
+ sb.append("\n");
+ appendFormula(sb, "Formula 1:", _formula1);
+ appendFormula(sb, "Formula 2:", _formula2);
+ sb.append("Regions: ");
+ int nRegions = _regions.getADDRStructureNumber();
+ for(int i=0; i
@@ -177,63 +171,7 @@ public final class DataValidityTable extends RecordAggregate {
return false;
}
- public void addDataValidation(HSSFDataValidation dataValidation, HSSFWorkbook workbook) {
-
- 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);
-
+ public void addDataValidation(DVRecord dvRecord) {
_validationList.add(dvRecord);
_headerRec.setDVRecNo(_validationList.size());
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/NumberPtg.java b/src/java/org/apache/poi/hssf/record/formula/NumberPtg.java
index 02b0075011..84d4a1704d 100644
--- a/src/java/org/apache/poi/hssf/record/formula/NumberPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/NumberPtg.java
@@ -36,7 +36,7 @@ public final class NumberPtg extends ScalarConstantPtg {
/** Create a NumberPtg from a byte array read from disk */
public NumberPtg(RecordInputStream in)
{
- field_1_value = in.readDouble();
+ this(in.readDouble());
}
/** Create a NumberPtg from a string representation of the number
@@ -45,9 +45,12 @@ public final class NumberPtg extends ScalarConstantPtg {
* @param value : String representation of a floating point number
*/
public NumberPtg(String value) {
- field_1_value = Double.parseDouble(value);
+ this(Double.parseDouble(value));
}
+ public NumberPtg(double value) {
+ field_1_value = value;
+ }
public double getValue()
{
@@ -67,6 +70,15 @@ public final class NumberPtg extends ScalarConstantPtg {
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();
}
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/Ptg.java b/src/java/org/apache/poi/hssf/record/formula/Ptg.java
index 7a882e4ae0..d1ea411cb9 100644
--- a/src/java/org/apache/poi/hssf/record/formula/Ptg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java
@@ -41,6 +41,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
* @author Jason Height (jheight at chariot dot net dot au)
*/
public abstract class Ptg implements Cloneable {
+ public static final Ptg[] EMPTY_PTG_ARRAY = { };
/* convert infix order ptg list to rpn order ptg list
* @return List ptgs in RPN order
@@ -250,6 +251,9 @@ public abstract class Ptg implements Cloneable {
}
}
private static Ptg[] toPtgArray(List l) {
+ if (l.isEmpty()) {
+ return EMPTY_PTG_ARRAY;
+ }
Ptg[] result = new Ptg[l.size()];
l.toArray(result);
return result;
diff --git a/src/java/org/apache/poi/hssf/usermodel/DVConstraint.java b/src/java/org/apache/poi/hssf/usermodel/DVConstraint.java
new file mode 100644
index 0000000000..d4f147316b
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/usermodel/DVConstraint.java
@@ -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 SimpleDateFormat can be used
+ * @see SimpleDateFormat
+ */
+ 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 null
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 null
if numberStr is null
+ */
+ 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 null
if timeStr is null
+ */
+ private static Double convertTime(String timeStr) {
+ if (timeStr == null) {
+ return null;
+ }
+ return new Double(HSSFDateUtil.convertTime(timeStr));
+ }
+ /**
+ * @param dateFormat pass null
for default YYYYMMDD
+ * @return null
if timeStr is null
+ */
+ 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 null
+ */
+ 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 true
if this constraint is a 'list' validation
+ */
+ public boolean isListValidationType() {
+ return _validationType == VT.LIST;
+ }
+ /**
+ * Convenience method
+ * @return true
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 null
+ */
+ 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 null
+ */
+ 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 null
+ */
+ 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 null
+ */
+ public Double getValue2() {
+ return _value2;
+ }
+ /**
+ * Sets a numeric value for expression 2.
+ */
+ public void setValue2(double value2) {
+ _formula2 = null;
+ _value2 = new Double(value2);
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDataValidation.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDataValidation.java
new file mode 100644
index 0000000000..3be3843692
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDataValidation.java
@@ -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 true
if this object should treats empty as valid value , false
+ * 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 true
if a list should display the values into a drop down list ,
+ * false
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 true
if an prompt box should be displayed , false
otherwise
+ */
+ public void setShowPromptBox(boolean show) {
+ _showPromptBox = show;
+ }
+
+ /**
+ * @param show true
if an prompt box should be displayed , false
otherwise
+ */
+ public boolean getShowPromptBox() {
+ return _showPromptBox;
+ }
+
+ /**
+ * 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) {
+ _showErrorBox = show;
+ }
+
+ /**
+ * @return true
if an error box should be displayed , false
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 null
+ */
+ public String getPromptBoxTitle() {
+ return _prompt_title;
+ }
+
+ /**
+ * @return Prompt box's text or null
+ */
+ 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 null
+ */
+ public String getErrorBoxTitle() {
+ return _error_title;
+ }
+
+ /**
+ * @return Error box's text or null
+ */
+ public String getErrorBoxText() {
+ return _error_text;
+ }
+
+ public DVRecord createDVRecord(HSSFWorkbook workbook) {
+
+ FormulaPair fp = _constraint.createFormulas(workbook);
+
+ return new DVRecord(_constraint.getValidationType(),
+ _constraint.getOperator(),
+ _errorStyle, _emptyCellAllowed, getSuppressDropDownArrow(),
+ _constraint.isExplicitList(),
+ _showPromptBox, _prompt_title, _prompt_text,
+ _showErrorBox, _error_title, _error_text,
+ fp.getFormula1(), fp.getFormula2(),
+ _regions);
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java
index ab353ca02c..457f0b9ed1 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java
@@ -16,17 +16,12 @@
==================================================================== */
-
-/*
- * DateUtil.java
- *
- * Created on January 19, 2002, 9:30 AM
- */
package org.apache.poi.hssf.usermodel;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.regex.Pattern;
/**
* Contains methods for dealing with Excel dates.
@@ -38,17 +33,20 @@ import java.util.GregorianCalendar;
* @author Alex Jacoby (ajacoby at gmail.com)
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
*/
-
-public class HSSFDateUtil
-{
- private HSSFDateUtil()
- {
+public final class HSSFDateUtil {
+ private HSSFDateUtil() {
+ // no instances of this class
}
+ private static final int SECONDS_PER_MINUTE = 60;
+ private static final int MINUTES_PER_HOUR = 60;
+ private static final int HOURS_PER_DAY = 24;
+ private static final int SECONDS_PER_DAY = (HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
+
+ private static final int BAD_DATE = -1; // used to specify that date is invalid
+ private static final long DAY_MILLISECONDS = SECONDS_PER_DAY * 1000L;
+
+ private static final Pattern TIME_SEPARATOR_PATTERN = Pattern.compile(":");
- private static final int BAD_DATE =
- -1; // used to specify that date is invalid
- private static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
-
/**
* Given a Date, converts it into a double representing its internal Excel representation,
* which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds.
@@ -57,7 +55,7 @@ public class HSSFDateUtil
* @param date the Date
*/
public static double getExcelDate(Date date) {
- return getExcelDate(date, false);
+ return getExcelDate(date, false);
}
/**
* Given a Date, converts it into a double representing its internal Excel representation,
@@ -74,8 +72,8 @@ public class HSSFDateUtil
}
/**
* Given a Date in the form of a Calendar, converts it into a double
- * representing its internal Excel representation, which is the
- * number of days since 1/1/1900. Fractional days represent hours,
+ * representing its internal Excel representation, which is the
+ * number of days since 1/1/1900. Fractional days represent hours,
* minutes, and seconds.
*
* @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1)
@@ -83,41 +81,40 @@ public class HSSFDateUtil
* @param use1904windowing Should 1900 or 1904 date windowing be used?
*/
public static double getExcelDate(Calendar date, boolean use1904windowing) {
- // Don't alter the supplied Calendar as we do our work
- return internalGetExcelDate( (Calendar)date.clone(), use1904windowing );
+ // Don't alter the supplied Calendar as we do our work
+ return internalGetExcelDate( (Calendar)date.clone(), use1904windowing );
}
private static double internalGetExcelDate(Calendar date, boolean use1904windowing) {
- if ((!use1904windowing && date.get(Calendar.YEAR) < 1900) ||
- (use1904windowing && date.get(Calendar.YEAR) < 1904))
+ if ((!use1904windowing && date.get(Calendar.YEAR) < 1900) ||
+ (use1904windowing && date.get(Calendar.YEAR) < 1904))
{
return BAD_DATE;
- } else {
- // Because of daylight time saving we cannot use
- // date.getTime() - calStart.getTimeInMillis()
- // as the difference in milliseconds between 00:00 and 04:00
- // can be 3, 4 or 5 hours but Excel expects it to always
- // be 4 hours.
- // E.g. 2004-03-28 04:00 CEST - 2004-03-28 00:00 CET is 3 hours
- // and 2004-10-31 04:00 CET - 2004-10-31 00:00 CEST is 5 hours
- double fraction = (((date.get(Calendar.HOUR_OF_DAY) * 60
- + date.get(Calendar.MINUTE)
- ) * 60 + date.get(Calendar.SECOND)
- ) * 1000 + date.get(Calendar.MILLISECOND)
- ) / ( double ) DAY_MILLISECONDS;
- Calendar calStart = dayStart(date);
-
- double value = fraction + absoluteDay(calStart, use1904windowing);
-
- if (!use1904windowing && value >= 60) {
- value++;
- } else if (use1904windowing) {
- value--;
- }
-
- return value;
}
+ // Because of daylight time saving we cannot use
+ // date.getTime() - calStart.getTimeInMillis()
+ // as the difference in milliseconds between 00:00 and 04:00
+ // can be 3, 4 or 5 hours but Excel expects it to always
+ // be 4 hours.
+ // E.g. 2004-03-28 04:00 CEST - 2004-03-28 00:00 CET is 3 hours
+ // and 2004-10-31 04:00 CET - 2004-10-31 00:00 CEST is 5 hours
+ double fraction = (((date.get(Calendar.HOUR_OF_DAY) * 60
+ + date.get(Calendar.MINUTE)
+ ) * 60 + date.get(Calendar.SECOND)
+ ) * 1000 + date.get(Calendar.MILLISECOND)
+ ) / ( double ) DAY_MILLISECONDS;
+ Calendar calStart = dayStart(date);
+
+ double value = fraction + absoluteDay(calStart, use1904windowing);
+
+ if (!use1904windowing && value >= 60) {
+ value++;
+ } else if (use1904windowing) {
+ value--;
+ }
+
+ return value;
}
-
+
/**
* Given an Excel date with using 1900 date windowing, and
* converts it to a java.util.Date.
@@ -130,13 +127,13 @@ public class HSSFDateUtil
* Europe/Copenhagen
, on 2004-03-28 the minute after
* 01:59 CET is 03:00 CEST, if the excel date represents a time between
* 02:00 and 03:00 then it is converted to past 03:00 summer time
- *
+ *
* @param date The Excel date.
* @return Java representation of the date, or null if date is not a valid Excel date
* @see java.util.TimeZone
*/
public static Date getJavaDate(double date) {
- return getJavaDate(date, false);
+ return getJavaDate(date, false);
}
/**
* Given an Excel date with either 1900 or 1904 date windowing,
@@ -158,94 +155,90 @@ public class HSSFDateUtil
* @see java.util.TimeZone
*/
public static Date getJavaDate(double date, boolean use1904windowing) {
- if (isValidExcelDate(date)) {
- int startYear = 1900;
- int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
- int wholeDays = (int)Math.floor(date);
- if (use1904windowing) {
- startYear = 1904;
- dayAdjust = 1; // 1904 date windowing uses 1/2/1904 as the first day
- }
- else if (wholeDays < 61) {
- // Date is prior to 3/1/1900, so adjust because Excel thinks 2/29/1900 exists
- // If Excel date == 2/29/1900, will become 3/1/1900 in Java representation
- dayAdjust = 0;
- }
- GregorianCalendar calendar = new GregorianCalendar(startYear,0,
- wholeDays + dayAdjust);
- int millisecondsInDay = (int)((date - Math.floor(date)) *
- DAY_MILLISECONDS + 0.5);
- calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
- return calendar.getTime();
- }
- else {
+ if (!isValidExcelDate(date)) {
return null;
}
+ int startYear = 1900;
+ int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
+ int wholeDays = (int)Math.floor(date);
+ if (use1904windowing) {
+ startYear = 1904;
+ dayAdjust = 1; // 1904 date windowing uses 1/2/1904 as the first day
+ }
+ else if (wholeDays < 61) {
+ // Date is prior to 3/1/1900, so adjust because Excel thinks 2/29/1900 exists
+ // If Excel date == 2/29/1900, will become 3/1/1900 in Java representation
+ dayAdjust = 0;
+ }
+ GregorianCalendar calendar = new GregorianCalendar(startYear,0,
+ wholeDays + dayAdjust);
+ int millisecondsInDay = (int)((date - Math.floor(date)) *
+ DAY_MILLISECONDS + 0.5);
+ calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
+ return calendar.getTime();
}
-
+
/**
* Given a format ID and its format String, will check to see if the
* format represents a date format or not.
* Firstly, it will check to see if the format ID corresponds to an
- * internal excel date format (eg most US date formats)
+ * internal excel date format (eg most US date formats)
* If not, it will check to see if the format string only contains
* date formatting characters (ymd-/), which covers most
* non US date formats.
- *
+ *
* @param formatIndex The index of the format, eg from ExtendedFormatRecord.getFormatIndex
* @param formatString The format string, eg from FormatRecord.getFormatString
* @see #isInternalDateFormat(int)
*/
public static boolean isADateFormat(int formatIndex, String formatString) {
- // First up, is this an internal date format?
- if(isInternalDateFormat(formatIndex)) {
- return true;
- }
-
- // If we didn't get a real string, it can't be
- if(formatString == null || formatString.length() == 0) {
- return false;
- }
-
- String fs = formatString;
-
- // Translate \- into just -, before matching
- fs = fs.replaceAll("\\\\-","-");
- // And \, into ,
- fs = fs.replaceAll("\\\\,",",");
- // And '\ ' into ' '
- fs = fs.replaceAll("\\\\ "," ");
-
- // If it end in ;@, that's some crazy dd/mm vs mm/dd
- // switching stuff, which we can ignore
- fs = fs.replaceAll(";@", "");
-
- // If it starts with [$-...], then could be a date, but
- // who knows what that starting bit is all about
- fs = fs.replaceAll("^\\[\\$\\-.*?\\]", "");
-
- // If it starts with something like [Black] or [Yellow],
- // then it could be a date
- fs = fs.replaceAll("^\\[[a-zA-Z]+\\]", "");
-
- // Otherwise, check it's only made up, in any case, of:
- // y m d h s - / , . :
- // optionally followed by AM/PM
- if(fs.matches("^[yYmMdDhHsS\\-/,. :]+[ampAMP/]*$")) {
- return true;
- }
-
- return false;
+ // First up, is this an internal date format?
+ if(isInternalDateFormat(formatIndex)) {
+ return true;
+ }
+
+ // If we didn't get a real string, it can't be
+ if(formatString == null || formatString.length() == 0) {
+ return false;
+ }
+
+ String fs = formatString;
+
+ // Translate \- into just -, before matching
+ fs = fs.replaceAll("\\\\-","-");
+ // And \, into ,
+ fs = fs.replaceAll("\\\\,",",");
+ // And '\ ' into ' '
+ fs = fs.replaceAll("\\\\ "," ");
+
+ // If it end in ;@, that's some crazy dd/mm vs mm/dd
+ // switching stuff, which we can ignore
+ fs = fs.replaceAll(";@", "");
+
+ // If it starts with [$-...], then could be a date, but
+ // who knows what that starting bit is all about
+ fs = fs.replaceAll("^\\[\\$\\-.*?\\]", "");
+
+ // If it starts with something like [Black] or [Yellow],
+ // then it could be a date
+ fs = fs.replaceAll("^\\[[a-zA-Z]+\\]", "");
+
+ // Otherwise, check it's only made up, in any case, of:
+ // y m d h s - / , . :
+ // optionally followed by AM/PM
+ if(fs.matches("^[yYmMdDhHsS\\-/,. :]+[ampAMP/]*$")) {
+ return true;
+ }
+
+ return false;
}
/**
* Given a format ID this will check whether the format represents
* an internal excel date format or not.
- * @see #isADateFormat(int, java.lang.String)
+ * @see #isADateFormat(int, java.lang.String)
*/
public static boolean isInternalDateFormat(int format) {
- boolean retval =false;
-
switch(format) {
// Internal Date Formats as described on page 427 in
// Microsoft Excel Dev's Kit...
@@ -261,27 +254,22 @@ public class HSSFDateUtil
case 0x2d:
case 0x2e:
case 0x2f:
- retval = true;
- break;
-
- default:
- retval = false;
- break;
+ return true;
}
- return retval;
+ return false;
}
/**
* Check if a cell contains a date
- * Since dates are stored internally in Excel as double values
- * we infer it is a date if it is formatted as such.
+ * Since dates are stored internally in Excel as double values
+ * we infer it is a date if it is formatted as such.
* @see #isADateFormat(int, String)
* @see #isInternalDateFormat(int)
*/
public static boolean isCellDateFormatted(HSSFCell cell) {
if (cell == null) return false;
boolean bDate = false;
-
+
double d = cell.getNumericCellValue();
if ( HSSFDateUtil.isValidExcelDate(d) ) {
HSSFCellStyle style = cell.getCellStyle();
@@ -302,7 +290,7 @@ public class HSSFDateUtil
public static boolean isCellInternalDateFormatted(HSSFCell cell) {
if (cell == null) return false;
boolean bDate = false;
-
+
double d = cell.getNumericCellValue();
if ( HSSFDateUtil.isValidExcelDate(d) ) {
HSSFCellStyle style = cell.getCellStyle();
@@ -344,7 +332,7 @@ public class HSSFDateUtil
*
* @return days number of days in years prior to yr.
* @param yr a year (1900 < yr < 4000)
- * @param use1904windowing
+ * @param use1904windowing
* @exception IllegalArgumentException if year is outside of range.
*/
@@ -353,16 +341,16 @@ public class HSSFDateUtil
if ((!use1904windowing && yr < 1900) || (use1904windowing && yr < 1900)) {
throw new IllegalArgumentException("'year' must be 1900 or greater");
}
-
+
int yr1 = yr - 1;
int leapDays = yr1 / 4 // plus julian leap days in prior years
- yr1 / 100 // minus prior century years
- + yr1 / 400 // plus years divisible by 400
+ + yr1 / 400 // plus years divisible by 400
- 460; // leap days in previous 1900 years
-
+
return 365 * (yr - (use1904windowing ? 1904 : 1900)) + leapDays;
}
-
+
// set HH:MM:SS fields of cal to 00:00:00:000
private static Calendar dayStart(final Calendar cal)
{
@@ -377,5 +365,95 @@ public class HSSFDateUtil
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;
+ }
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
index 9b6c206190..a99e48b64e 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
@@ -38,7 +38,6 @@ import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.aggregates.DataValidityTable;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.RefPtg;
-import org.apache.poi.hssf.util.HSSFDataValidation;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.POILogFactory;
@@ -382,7 +381,8 @@ public final class HSSFSheet {
}
DataValidityTable dvt = sheet.getOrCreateDataValidityTable();
- dvt.addDataValidation(dataValidation, workbook);
+ DVRecord dvRecord = dataValidation.createDVRecord(workbook);
+ dvt.addDataValidation(dvRecord);
}
diff --git a/src/java/org/apache/poi/hssf/util/CellRangeAddress.java b/src/java/org/apache/poi/hssf/util/CellRangeAddress.java
new file mode 100644
index 0000000000..2f5d24aa02
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/util/CellRangeAddress.java
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/apache/poi/hssf/util/CellRangeAddressList.java b/src/java/org/apache/poi/hssf/util/CellRangeAddressList.java
new file mode 100644
index 0000000000..d52219769d
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/util/CellRangeAddressList.java
@@ -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.
+ *
Title: HSSFCellRangeAddress
- *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.
- *Copyright: Copyright (c) 2004
- *Company:
- * @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; - } - } -} - - diff --git a/src/java/org/apache/poi/hssf/util/HSSFDataValidation.java b/src/java/org/apache/poi/hssf/util/HSSFDataValidation.java deleted file mode 100644 index 4d8f48b929..0000000000 --- a/src/java/org/apache/poi/hssf/util/HSSFDataValidation.java +++ /dev/null @@ -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; - -/** - *Title: HSSFDataValidation
- *Description: Utilty class for creating data validation cells
- *Copyright: Copyright (c) 2004
- *Company:
- * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) - * @version 2.0-pre - */ - -public class HSSFDataValidation -{ - /** - * Validation data type constants - */ - /** - * Any type - */ - public static final int DATA_TYPE_ANY = 0x00; - /** - * Integer type - */ - public static final int DATA_TYPE_INTEGER = 0x01; - /** - * Decimal type - */ - public static final int DATA_TYPE_DECIMAL = 0x02; - /** - * List type ( combo box type ) - */ - public static final int DATA_TYPE_LIST = 0x03; - /** - * Date type - */ - public static final int DATA_TYPE_DATE = 0x04; - /** - * Time type - */ - public static final int DATA_TYPE_TIME = 0x05; - /** - * String length type - */ - public static final int DATA_TYPE_TEXT_LENGTH = 0x06; - /** - * Formula ( custom ) type - */ - public static final int DATA_TYPE_FORMULA = 0x07; - - /** - * Error style constants for error box - */ - /** - * STOP style like - */ - public static final int ERROR_STYLE_STOP = 0x00; - /** - * WARNING style like - */ - public static final int ERROR_STYLE_WARNING = 0x01; - /** - * INFO style like - */ - public static final int ERROR_STYLE_INFO = 0x02; - - /** - * Condition operator - */ - public static final int OPERATOR_BETWEEN = 0x00; - public static final int OPERATOR_NOT_BETWEEN = 0x01; - public static final int OPERATOR_EQUAL = 0x02; - public static final int OPERATOR_NOT_EQUAL = 0x03; - public static final int OPERATOR_GREATER_THAN = 0x04; - public static final int OPERATOR_LESS_THAN = 0x05; - public static final int OPERATOR_GREATER_OR_EQUAL = 0x06; - public static final int OPERATOR_LESS_OR_EQUAL = 0x07; - - private short _first_row = 0; - private short _first_col = 0; - private short _last_row = 0; - private short _last_col = 0; - - private String _prompt_title = null; - private String _prompt_text = null; - private String _error_title = null; - private String _error_text = null; - private String _string_first_formula = null; - private String _string_sec_formula = null; - - private int _data_type = HSSFDataValidation.DATA_TYPE_ANY; - private int _error_style = HSSFDataValidation.ERROR_STYLE_STOP; - private boolean _list_explicit_formula = true; - private boolean _empty_cell_allowed = true; - private boolean _surpress_dropdown_arrow = false; - private boolean _show_prompt_box = true; - private boolean _show_error_box = true; - private int _operator = HSSFDataValidation.OPERATOR_BETWEEN; - - - /** - * Empty constructor - */ - public HSSFDataValidation( ) - { - } - - /** - * Constructor wich initializes the cell range on wich this object will be applied - * @param first_row First row - * @param first_col First column - * @param last_row Last row - * @param last_col Last column - */ - public HSSFDataValidation( short first_row, short first_col, short last_row, short last_col ) - { - this._first_row = first_row; - this._first_col = first_col; - this._last_row = last_row; - this._last_col = last_col; - } - - /** - * Set the type of this object - * @param data_type The type - * @see DATA_TYPE_ANY, DATA_TYPE_INTEGER, DATA_TYPE_DECIMNAL, DATA_TYPE_LIST, DATA_TYPE_DATE, - * DATA_TYPE_TIME, DATA_TYPE_TEXT_LENTGH, DATA_TYPE_FORMULA - */ - public void setDataValidationType( int data_type ) - { - this._data_type = data_type; - } - - /** - * The data type of this object - * @return The type - * @see DATA_TYPE_ANY, DATA_TYPE_INTEGER, DATA_TYPE_DECIMNAL, DATA_TYPE_LIST, DATA_TYPE_DATE, - * DATA_TYPE_TIME, DATA_TYPE_TEXT_LENTGH, DATA_TYPE_FORMULA - */ - public int getDataValidationType() - { - return this._data_type; - } - - /** - * Sets the error style for error box - * @param error_style Error style constant - * @see ERROR_STYLE_STOP, ERROR_STYLE_WARNING, ERROR_STYLE_INFO - */ - public void setErrorStyle( int error_style ) - { - this._error_style = error_style; - } - - /** - * returns the error style of errror box - * @return the style constant - * @see ERROR_STYLE_STOP, ERROR_STYLE_WARNING, ERROR_STYLE_INFO - */ - public int getErrorStyle( ) - { - return this._error_style; - } - - /** - * If this object has an explicit formula . This is useful only for list data validation object - * @param explicit True if use an explicit formula - */ - public void setExplicitListFormula( boolean explicit ) - { - this._list_explicit_formula = explicit; - } - - /** - * Returns the settings for explicit formula . This is useful only for list data validation objects. - * This method always returns false if the object isn't a list validation object - * @see setDataValidationType( int data_type ) - * @return - */ - public boolean getExplicitListFormula( ) - { - if ( this._data_type != HSSFDataValidation.DATA_TYPE_LIST ) - { - return false; - } - return this._list_explicit_formula ; - } - - /** - * Sets if this object allows empty as a valid value - * @param allowed True if this object should treats empty as valid value , false otherwise - */ - public void setEmptyCellAllowed( boolean allowed ) - { - this._empty_cell_allowed = allowed; - } - - /** - * Retrieve the settings for empty cells allowed - * @return True if this object should treats empty as valid value , false otherwise - */ - public boolean getEmptyCellAllowed( ) - { - return this._empty_cell_allowed ; - } - /** - * @deprecated - (Jul-2008) use setSuppressDropDownArrow - */ - public void setSurppressDropDownArrow( boolean suppress ) { - setSuppressDropDownArrow(suppress); - } - /** - * @deprecated - (Jul-2008) use getSuppressDropDownArrow - */ - public boolean getSurppressDropDownArrow( ) { - return getSuppressDropDownArrow(); - } - - /** - * Useful for list validation objects . - * @param surppres True if a list should display the values into a drop down list , false otherwise . - * In other words , if a list should display the arrow sign on its right side - */ - public void setSuppressDropDownArrow( boolean surppres ) - { - this._surpress_dropdown_arrow = surppres; - } - - /** - * Useful only list validation objects . - * This method always returns false if the object isn't a list validation object - * @return True if a list should display the values into a drop down list , false otherwise . - * @see setDataValidationType( int data_type ) - */ - public boolean getSuppressDropDownArrow( ) - { - if ( this._data_type != HSSFDataValidation.DATA_TYPE_LIST ) - { - return false; - } - return this._surpress_dropdown_arrow ; - } - - /** - * Sets the behaviour when a cell which belongs to this object is selected - * @param show True if an prompt box should be displayed , false otherwise - */ - public void setShowPromptBox( boolean show ) - { - this._show_prompt_box = show; - } - - /** - * @param show True if an prompt box should be displayed , false otherwise - */ - public boolean getShowPromptBox( ) - { - if ( (this.getPromptBoxText() == null) && (this.getPromptBoxTitle() == null) ) - { - return false; - } - return this._show_prompt_box ; - } - - /** - * Sets the behaviour when an invalid value is entered - * @param show True if an error box should be displayed , false otherwise - */ - public void setShowErrorBox( boolean show ) - { - this._show_error_box = show; - } - - /** - * @return True if an error box should be displayed , false otherwise - */ - public boolean getShowErrorBox( ) - { - if ( (this.getErrorBoxText() == null) && (this.getErrorBoxTitle() == null) ) - { - return false; - } - return this._show_error_box ; - } - - /** - * Sets the operator involved in the formula whic governs this object - * Example : if you wants that a cell to accept only values between 1 and 5 , which - * mathematically means 1 <= value <= 5 , then the operator should be OPERATOR_BETWEEN - * @param operator A constant for operator - * @see OPERATOR_BETWEEN, OPERATOR_NOT_BETWEEN, OPERATOR_EQUAL, OPERATOR_NOT_EQUAL - * OPERATOR_GREATER_THAN, OPERATOR_LESS_THAN, OPERATOR_GREATER_OR_EQUAL, - * OPERATOR_LESS_OR_EQUAL - */ - public void setOperator( int operator ) - { - this._operator = operator; - } - - /** - * Retrieves the operator used for this object's formula - * @return - * @see OPERATOR_BETWEEN, OPERATOR_NOT_BETWEEN, OPERATOR_EQUAL, OPERATOR_NOT_EQUAL - * OPERATOR_GREATER_THAN, OPERATOR_LESS_THAN, OPERATOR_GREATER_OR_EQUAL, - * OPERATOR_LESS_OR_EQUAL - */ - public int getOperator() - { - return this._operator; - } - - /** - * Sets the title and text for the prompt box . Prompt box is displayed when the user - * selects a cell which belongs to this validation object . In order for a prompt box - * to be displayed you should also use method setShowPromptBox( boolean show ) - * @param title The prompt box's title - * @param text The prompt box's text - * @see setShowPromptBox( boolean show ) - */ - public void createPromptBox( String title, String text ) - { - this._prompt_title = title; - this._prompt_text = text; - this.setShowPromptBox(true); - } - - /** - * Returns the prompt box's title - * @return Prompt box's title or null - */ - public String getPromptBoxTitle( ) - { - return this._prompt_title; - } - - /** - * Returns the prompt box's text - * @return Prompt box's text or null - */ - public String getPromptBoxText( ) - { - return this._prompt_text; - } - - /** - * Sets the title and text for the error box . Error box is displayed when the user - * enters an invalid value int o a cell which belongs to this validation object . - * In order for an error box to be displayed you should also use method - * setShowErrorBox( boolean show ) - * @param title The error box's title - * @param text The error box's text - * @see setShowErrorBox( boolean show ) - */ - public void createErrorBox( String title, String text ) - { - this._error_title = title; - this._error_text = text; - this.setShowErrorBox(true); - } - - /** - * Returns the error box's title - * @return Error box's title or null - */ - public String getErrorBoxTitle( ) - { - return this._error_title; - } - - /** - * Returns the error box's text - * @return Error box's text or null - */ - public String getErrorBoxText( ) - { - return this._error_text; - } - - /** - * Sets the first formula for this object . - * A formula is divided into three parts : first formula , operator and second formula . - * In other words , a formula contains a left oprand , an operator and a right operand. - * This is the general rule . An example is 1<= value <= 5 . In this case , - * the left operand ( or the first formula ) is the number 1 . The operator is - * OPERATOR_BETWEEN and the right operand ( or the second formula ) is 5 . - * @param formula - */ - public void setFirstFormula( String formula ) - { - this._string_first_formula = formula; - } - - /** - * Returns the first formula - * @return - */ - public String getFirstFormula( ) - { - return this._string_first_formula; - } - - /** - * Sets the first formula for this object . - * A formula is divided into three parts : first formula , operator and second formula . - * In other words , a formula contains a left oprand , an operator and a right operand. - * This is the general rule . An example is 1<= value <=5 . In this case , - * the left operand ( or the first formula ) is the number 1 . The operator is - * OPERATOR_BETWEEN and the right operand ( or the second formula ) is 5 . - * But there are cases when a second formula isn't needed : - * You want somethink like : all values less than 5 . In this case , there's only a first - * formula ( in our case 5 ) and the operator OPERATOR_LESS_THAN - * @param formula - */ - public void setSecondFormula( String formula ) - { - this._string_sec_formula = formula; - } - - /** - * Returns the second formula - * @return - */ - public String getSecondFormula( ) - { - return this._string_sec_formula; - } - - public void setFirstRow( short first_row ) - { - this._first_row = first_row; - } - - public void setFirstColumn( short first_column ) - { - this._first_col = first_column; - } - - public void setLastRow( short last_row ) - { - this._last_row = last_row; - } - - public void setLastColumn( short last_column ) - { - this._last_col = last_column; - } - - public short getFirstRow() - { - return this._first_row; - } - - public short getFirstColumn() - { - return this._first_col; - } - - public short getLastRow() - { - return this._last_row; - } - - public short getLastColumn() - { - return this._last_col; - } - -} \ No newline at end of file diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestDataValidation.java b/src/testcases/org/apache/poi/hssf/usermodel/TestDataValidation.java index 8c43fa74eb..b588c6e6cc 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestDataValidation.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestDataValidation.java @@ -21,7 +21,8 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.text.SimpleDateFormat; +import java.io.InputStream; +import java.io.PrintStream; import junit.framework.AssertionFailedError; import junit.framework.TestCase; @@ -31,877 +32,537 @@ import org.apache.poi.hssf.eventmodel.ERFListener; import org.apache.poi.hssf.eventmodel.EventRecordFactory; import org.apache.poi.hssf.record.DVRecord; import org.apache.poi.hssf.record.RecordFormatException; +import org.apache.poi.hssf.util.CellRangeAddressList; import org.apache.poi.hssf.util.HSSFColor; -import org.apache.poi.hssf.util.HSSFDataValidation; import org.apache.poi.hssf.util.Region; import org.apache.poi.poifs.filesystem.POIFSFileSystem; /** - *Title: TestDataValidation
- *Description: Class for testing Excel's data validation mechanism - * Second test : - * - - *
+ * Class for testing Excel's data validation mechanism + * * @author Dragos Buleandra ( dragos.buleandra@trade2b.ro ) */ -public class TestDataValidation extends TestCase -{ - - public void testDataValidation() throws Exception - { - System.out.println("\nTest no. 2 - Test Excel's Data validation mechanism"); - String resultFile = System.getProperty("java.io.tmpdir")+File.separator+"TestDataValidation.xls"; - HSSFWorkbook wb = new HSSFWorkbook(); - - HSSFCellStyle style_1 = this.createStyle( wb, HSSFCellStyle.ALIGN_LEFT ); - HSSFCellStyle style_2 = this.createStyle( wb, HSSFCellStyle.ALIGN_CENTER ); - HSSFCellStyle style_3 = this.createStyle( wb, HSSFCellStyle.ALIGN_CENTER, HSSFColor.GREY_25_PERCENT.index, true ); - HSSFCellStyle style_4 = this.createHeaderStyle(wb); - HSSFDataValidation data_validation = null; - - //data validation's number types - System.out.print(" Create sheet for Data Validation's number types ... "); - HSSFSheet fSheet = wb.createSheet("Number types"); - - //"Whole number" validation type - this.createDVTypeRow( wb, 0, style_3, "Whole number"); - this.createHeaderRow( wb, 0, style_4 ); - - short start_row = (short)fSheet.getPhysicalNumberOfRows(); - data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_INTEGER); - data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN); - data_validation.setFirstFormula("2"); - data_validation.setSecondFormula("6"); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 2 and 6 ", true, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)(start_row+1)); - data_validation.setLastRow((short)(start_row+1)); - data_validation.setEmptyCellAllowed(false); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 2 and 6 ", false, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" ); - - data_validation.setFirstRow((short)(start_row+2)); - data_validation.setLastRow((short)(start_row+2)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3", false, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" ); - - data_validation.setFirstRow((short)(start_row+3)); - data_validation.setLastRow((short)(start_row+3)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3", false, false, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+4)); - data_validation.setLastRow((short)(start_row+4)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3", true, false, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+5)); - data_validation.setLastRow((short)(start_row+5)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3", true, true, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+6)); - data_validation.setLastRow((short)(start_row+6)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP); - data_validation.setShowErrorBox(true); - data_validation.setFirstFormula("4"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 4", true, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)(start_row+7)); - data_validation.setLastRow((short)(start_row+7)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("4"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 4", false, true, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - //"Decimal" validation type - this.createDVTypeRow( wb, 0, style_3, "Decimal"); - this.createHeaderRow( wb, 0, style_4 ); - - start_row += (short)(8+4); - data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_DECIMAL); - data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN); - data_validation.setFirstFormula("2"); - data_validation.setSecondFormula("6"); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 2 and 6 ", true, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)(start_row+1)); - data_validation.setLastRow((short)(start_row+1)); - data_validation.setEmptyCellAllowed(false); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 2 and 6 ", false, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" ); - - data_validation.setFirstRow((short)(start_row+2)); - data_validation.setLastRow((short)(start_row+2)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3", false, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" ); - - data_validation.setFirstRow((short)(start_row+3)); - data_validation.setLastRow((short)(start_row+3)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3", false, false, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+4)); - data_validation.setLastRow((short)(start_row+4)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3", true, false, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+5)); - data_validation.setLastRow((short)(start_row+5)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3", true, true, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+6)); - data_validation.setLastRow((short)(start_row+6)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP); - data_validation.setShowErrorBox(true); - data_validation.setFirstFormula("4"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 4", true, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)(start_row+7)); - data_validation.setLastRow((short)(start_row+7)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("4"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 4", false, true, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - System.out.println("done !"); - - //"List" Data Validation type - /** @todo List*/ - System.out.print(" Create sheet for 'List' Data Validation type ... "); - fSheet = wb.createSheet("Lists"); - - this.createDVTypeRow( wb, 1, style_3, "Explicit lists - list items are explicitly provided"); - this.createDVDeescriptionRow( wb, 1, style_3, "Disadvantage - sum of item's length should be less than 255 characters"); - this.createHeaderRow( wb, 1, style_4 ); - - start_row = (short)fSheet.getPhysicalNumberOfRows(); - data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST); - data_validation.setFirstFormula("1+2+3"); - data_validation.setSecondFormula(null); - data_validation.setSurppressDropDownArrow(false); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", true, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" ); - - data_validation = new HSSFDataValidation((short)(start_row+1),(short)0,(short)(start_row+1),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST); - data_validation.setFirstFormula("4+5+6+7"); - data_validation.setSecondFormula(null); - data_validation.setSurppressDropDownArrow(false); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", false, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" ); - - data_validation = new HSSFDataValidation((short)(start_row+2),(short)0,(short)(start_row+2),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST); - data_validation.setFirstFormula("7+21"); - data_validation.setSecondFormula(null); - data_validation.setSurppressDropDownArrow(true); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", true, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" ); - - data_validation = new HSSFDataValidation((short)(start_row+3),(short)0,(short)(start_row+3),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST); - data_validation.setFirstFormula("8/2"); - data_validation.setSecondFormula(null); - data_validation.setSurppressDropDownArrow(true); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", false, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" ); - - this.createDVTypeRow( wb, 1, style_3, "Reference lists - list items are taken from others cells"); - this.createDVDeescriptionRow( wb, 1, style_3, "Advantage - no restriction regarding the sum of item's length"); - this.createHeaderRow( wb, 1, style_4 ); - - start_row += (short)(4+5); - String cellStrValue = "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "+ - "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "+ - "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "+ - "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "; - - String strFormula = "$A$100:$A$120"; - data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST); - data_validation.setFirstFormula(strFormula); - data_validation.setSecondFormula(null); - data_validation.setSurppressDropDownArrow(false); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, true, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" ); - - data_validation = new HSSFDataValidation((short)(start_row+1),(short)0,(short)(start_row+1),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST); - data_validation.setFirstFormula(strFormula); - data_validation.setSecondFormula(null); - data_validation.setSurppressDropDownArrow(false); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, false, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" ); - - data_validation = new HSSFDataValidation((short)(start_row+2),(short)0,(short)(start_row+2),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST); - data_validation.setFirstFormula(strFormula); - data_validation.setSecondFormula(null); - data_validation.setSurppressDropDownArrow(true); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, true, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" ); - - data_validation = new HSSFDataValidation((short)(start_row+3),(short)0,(short)(start_row+3),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST); - data_validation.setFirstFormula(strFormula); - data_validation.setSecondFormula(null); - data_validation.setSurppressDropDownArrow(true); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, false, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" ); - - for (int i=100; i<=120; i++) - { - HSSFRow currRow = fSheet.createRow(i); - currRow.createCell((short)0).setCellValue(cellStrValue); -// currRow.hide( true ); - } - - System.out.println("done !"); - - //Date/Time Validation type - System.out.print(" Create sheet for 'Date' and 'Time' Data Validation types ... "); - fSheet = wb.createSheet("Date_Time"); - SimpleDateFormat df = new SimpleDateFormat("m/d/yyyy"); - HSSFDataFormat dataFormat = wb.createDataFormat(); - short fmtDate = dataFormat.getFormat("m/d/yyyy"); - short fmtTime = dataFormat.getFormat("h:mm"); - HSSFCellStyle cellStyle_data = wb.createCellStyle(); - cellStyle_data.setDataFormat(fmtDate); - HSSFCellStyle cellStyle_time = wb.createCellStyle(); - cellStyle_time.setDataFormat(fmtTime); - - this.createDVTypeRow( wb, 2, style_3, "Date ( cells are already formated as date - m/d/yyyy)"); - this.createHeaderRow( wb, 2, style_4 ); - - start_row = (short)fSheet.getPhysicalNumberOfRows(); - data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_DATE); - data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN); - - data_validation.setFirstFormula( String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("1/2/2004"))) ); - data_validation.setSecondFormula( String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("1/6/2004"))) ); - - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 1/2/2004 and 1/6/2004 ", true, true, true ); - this.setCellFormat( fSheet, cellStyle_data ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)(start_row+1)); - data_validation.setLastRow((short)(start_row+1)); - data_validation.setEmptyCellAllowed(false); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 1/2/2004 and 1/6/2004 ", false, true, true ); - this.setCellFormat( fSheet, cellStyle_data ); - this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" ); - - data_validation.setFirstRow((short)(start_row+2)); - data_validation.setLastRow((short)(start_row+2)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3/2/2004", false, false, true ); - this.setCellFormat( fSheet, cellStyle_data ); - this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" ); - - data_validation.setFirstRow((short)(start_row+3)); - data_validation.setLastRow((short)(start_row+3)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3/2/2004", false, false, false ); - this.setCellFormat( fSheet, cellStyle_data ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+4)); - data_validation.setLastRow((short)(start_row+4)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3/2/2004", true, false, false ); - this.setCellFormat( fSheet, cellStyle_data ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+5)); - data_validation.setLastRow((short)(start_row+5)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3/2/2004", true, true, false ); - this.setCellFormat( fSheet, cellStyle_data ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+6)); - data_validation.setLastRow((short)(start_row+6)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP); - data_validation.setShowErrorBox(true); - data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 3/2/2004", true, false, true ); - this.setCellFormat( fSheet, cellStyle_data ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)(start_row+7)); - data_validation.setLastRow((short)(start_row+7)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/4/2004")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 3/4/2004", false, true, false ); - this.setCellFormat( fSheet, cellStyle_data ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - //"Time" validation type - this.createDVTypeRow( wb, 2, style_3, "Time ( cells are already formated as time - h:mm)"); - this.createHeaderRow( wb, 2, style_4 ); - - df = new SimpleDateFormat("hh:mm"); - - start_row += (short)(8+4); - data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_TIME); - data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN); - data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("12:00")))); - data_validation.setSecondFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("16:00")))); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 12:00 and 16:00 ", true, true, true ); - this.setCellFormat( fSheet, cellStyle_time ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)(start_row+1)); - data_validation.setLastRow((short)(start_row+1)); - data_validation.setEmptyCellAllowed(false); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 12:00 and 16:00 ", false, true, true ); - this.setCellFormat( fSheet, cellStyle_time ); - this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" ); - - data_validation.setFirstRow((short)(start_row+2)); - data_validation.setLastRow((short)(start_row+2)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("13:35")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 13:35", false, false, true ); - this.setCellFormat( fSheet, cellStyle_time ); - this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" ); - - data_validation.setFirstRow((short)(start_row+3)); - data_validation.setLastRow((short)(start_row+3)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("13:35")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 13:35", false, false, false ); - this.setCellFormat( fSheet, cellStyle_time ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+4)); - data_validation.setLastRow((short)(start_row+4)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("12:00")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 12:00", true, false, false ); - this.setCellFormat( fSheet, cellStyle_time ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+5)); - data_validation.setLastRow((short)(start_row+5)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("12:00")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 12:00", true, true, false ); - this.setCellFormat( fSheet, cellStyle_time ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)(start_row+6)); - data_validation.setLastRow((short)(start_row+6)); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP); - data_validation.setShowErrorBox(true); - data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("14:00")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 14:00", true, false, true ); - this.setCellFormat( fSheet, cellStyle_time ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)(start_row+7)); - data_validation.setLastRow((short)(start_row+7)); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("14:00")))); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 14:00", false, true, false ); - this.setCellFormat( fSheet, cellStyle_time ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - System.out.println("done !"); - - //"Text length" validation type - System.out.print(" Create sheet for 'Text length' Data Validation type... "); - fSheet = wb.createSheet("Text length"); - this.createHeaderRow( wb, 3, style_4 ); - - data_validation = new HSSFDataValidation((short)1,(short)0,(short)1,(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_TEXT_LENGTH); - data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN); - data_validation.setFirstFormula("2"); - data_validation.setSecondFormula("6"); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 2 and 6 ", true, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)2); - data_validation.setLastRow((short)2); - data_validation.setEmptyCellAllowed(false); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 2 and 6 ", false, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" ); - - data_validation.setFirstRow((short)3); - data_validation.setLastRow((short)3); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3", false, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" ); - - data_validation.setFirstRow((short)4); - data_validation.setLastRow((short)4); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3", false, false, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)5); - data_validation.setLastRow((short)5); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3", true, false, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)6); - data_validation.setLastRow((short)6); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("3"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3", true, true, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - - data_validation.setFirstRow((short)7); - data_validation.setLastRow((short)7); - data_validation.setEmptyCellAllowed(true); - data_validation.setShowPromptBox(false); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP); - data_validation.setShowErrorBox(true); - data_validation.setFirstFormula("4"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 4", true, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation.setFirstRow((short)8); - data_validation.setLastRow((short)8); - data_validation.setEmptyCellAllowed(false); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(false); - data_validation.setFirstFormula("4"); - data_validation.setSecondFormula(null); - data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 4", false, true, false ); - this.writeOtherSettings( fSheet, style_1, "-" ); - System.out.println("done !"); - - //Custom Validation type - System.out.print(" Create sheet for 'Custom' Data Validation type ... "); - fSheet = wb.createSheet("Custom"); - this.createHeaderRow( wb, 4, style_4 ); - - data_validation = new HSSFDataValidation((short)1,(short)0,(short)1,(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_FORMULA); - data_validation.setFirstFormula("ISNUMBER($A2)"); - data_validation.setSecondFormula(null); - data_validation.setShowPromptBox(true); - data_validation.setShowErrorBox(true); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !"); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "ISNUMBER(A2)", true, true, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" ); - - data_validation = new HSSFDataValidation((short)2,(short)0,(short)2,(short)0); - data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_FORMULA); - data_validation.setFirstFormula("IF(SUM(A2:A3)=5,TRUE,FALSE)"); - data_validation.setSecondFormula(null); - data_validation.setShowPromptBox(false); - data_validation.setShowErrorBox(true); - data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING); - data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !"); - data_validation.setEmptyCellAllowed(false); - fSheet.addValidationData(data_validation); - this.writeDataValidationSettings( fSheet, style_1, style_2, "IF(SUM(A2:A3)=5,TRUE,FALSE)", false, false, true ); - this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" ); - - System.out.println("done !"); - - //so , everything it's ok for now ; it remains for you to open the file - System.out.println("\n Everything it's ok since we've got so far -:) !\n"+ - " In order to complete the test , it remains for you to open the file \n"+ - " and see if there are four sheets , as described !"); - System.out.println(" File was saved in \""+resultFile+"\""); - - FileOutputStream fileOut = new FileOutputStream(resultFile); - wb.write(fileOut); - fileOut.close(); +public final class TestDataValidation extends TestCase { + + /** Convenient access to ERROR_STYLE constants */ + private static final HSSFDataValidation.ErrorStyle ES = null; + /** Convenient access to OPERATOR constants */ + private static final DVConstraint.ValidationType VT = null; + /** Convenient access to OPERATOR constants */ + private static final DVConstraint.OperatorType OP = null; + + private static void log(String msg) { + if (false) { // successful tests should be silent + System.out.println(msg); + } + } + + private static final class ValidationAdder { + + private final HSSFCellStyle _style_1; + private final HSSFCellStyle _style_2; + private final int _validationType; + private final HSSFSheet _sheet; + private int _currentRowIndex; + private final HSSFCellStyle _cellStyle; + + public ValidationAdder(HSSFSheet fSheet, HSSFCellStyle style_1, HSSFCellStyle style_2, + HSSFCellStyle cellStyle, int validationType) { + _sheet = fSheet; + _style_1 = style_1; + _style_2 = style_2; + _cellStyle = cellStyle; + _validationType = validationType; + _currentRowIndex = fSheet.getPhysicalNumberOfRows(); + } + public void addValidation(int operatorType, String firstFormula, String secondFormula, + int errorStyle, String ruleDescr, String promptDescr, + boolean allowEmpty, boolean inputBox, boolean errorBox) { + String[] explicitListValues = null; + + addValidationInternal(operatorType, firstFormula, secondFormula, errorStyle, ruleDescr, + promptDescr, allowEmpty, inputBox, errorBox, true, + explicitListValues); + } + + private void addValidationInternal(int operatorType, String firstFormula, + String secondFormula, int errorStyle, String ruleDescr, String promptDescr, + boolean allowEmpty, boolean inputBox, boolean errorBox, boolean suppressDropDown, + String[] explicitListValues) { + int rowNum = _currentRowIndex++; + + DVConstraint dc = createConstraint(operatorType, firstFormula, secondFormula, explicitListValues); + + HSSFDataValidation dv = new HSSFDataValidation(new CellRangeAddressList(rowNum, rowNum, 0, 0), dc); + + dv.setEmptyCellAllowed(allowEmpty); + dv.setErrorStyle(errorStyle); + dv.createErrorBox("Invalid Input", "Something is wrong - check condition!"); + dv.createPromptBox("Validated Cell", "Allowable values have been restricted"); + + dv.setShowPromptBox(inputBox); + dv.setShowErrorBox(errorBox); + dv.setSuppressDropDownArrow(suppressDropDown); + + + _sheet.addValidationData(dv); + writeDataValidationSettings(_sheet, _style_1, _style_2, ruleDescr, allowEmpty, + inputBox, errorBox); + if (_cellStyle != null) { + HSSFRow row = _sheet.getRow(_sheet.getPhysicalNumberOfRows() - 1); + HSSFCell cell = row.createCell((short) 0); + cell.setCellStyle(_cellStyle); + } + writeOtherSettings(_sheet, _style_1, promptDescr); + } + private DVConstraint createConstraint(int operatorType, String firstFormula, + String secondFormula, String[] explicitListValues) { + if (_validationType == VT.LIST) { + if (explicitListValues != null) { + return DVConstraint.createExplicitListConstraint(explicitListValues); + } + return DVConstraint.createFormulaListConstraint(firstFormula); + } + if (_validationType == VT.TIME) { + return DVConstraint.createTimeConstraint(operatorType, firstFormula, secondFormula); + } + if (_validationType == VT.DATE) { + return DVConstraint.createDateConstraint(operatorType, firstFormula, secondFormula, null); + } + if (_validationType == VT.FORMULA) { + return DVConstraint.createFormulaConstraint(firstFormula); + } + return DVConstraint.createNumericConstraint(_validationType, operatorType, firstFormula, secondFormula); + } + /** + * writes plain text values into cells in a tabular format to form comments readable from within + * the spreadsheet. + */ + private static void writeDataValidationSettings(HSSFSheet sheet, HSSFCellStyle style_1, + HSSFCellStyle style_2, String strCondition, boolean allowEmpty, boolean inputBox, + boolean errorBox) { + HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows()); + // condition's string + HSSFCell cell = row.createCell((short) 1); + cell.setCellStyle(style_1); + setCellValue(cell, strCondition); + // allow empty cells + cell = row.createCell((short) 2); + cell.setCellStyle(style_2); + setCellValue(cell, ((allowEmpty) ? "yes" : "no")); + // show input box + cell = row.createCell((short) 3); + cell.setCellStyle(style_2); + setCellValue(cell, ((inputBox) ? "yes" : "no")); + // show error box + cell = row.createCell((short) 4); + cell.setCellStyle(style_2); + setCellValue(cell, ((errorBox) ? "yes" : "no")); + } + private static void writeOtherSettings(HSSFSheet sheet, HSSFCellStyle style, + String strStettings) { + HSSFRow row = sheet.getRow(sheet.getPhysicalNumberOfRows() - 1); + HSSFCell cell = row.createCell((short) 5); + cell.setCellStyle(style); + setCellValue(cell, strStettings); + } + public void addListValidation(String[] explicitListValues, String listFormula, String listValsDescr, + boolean allowEmpty, boolean suppressDropDown) { + String promptDescr = (allowEmpty ? "empty ok" : "not empty") + + ", " + (suppressDropDown ? "no drop-down" : "drop-down"); + addValidationInternal(VT.LIST, listFormula, null, ES.STOP, listValsDescr, promptDescr, + allowEmpty, false, true, suppressDropDown, explicitListValues); + } + } + + /** + * Manages the cell styles used for formatting the output spreadsheet + */ + private static final class WorkbookFormatter { + + private final HSSFWorkbook _wb; + private final HSSFCellStyle _style_1; + private final HSSFCellStyle _style_2; + private final HSSFCellStyle _style_3; + private final HSSFCellStyle _style_4; + private HSSFSheet _currentSheet; + + public WorkbookFormatter(HSSFWorkbook wb) { + _wb = wb; + _style_1 = createStyle( wb, HSSFCellStyle.ALIGN_LEFT ); + _style_2 = createStyle( wb, HSSFCellStyle.ALIGN_CENTER ); + _style_3 = createStyle( wb, HSSFCellStyle.ALIGN_CENTER, HSSFColor.GREY_25_PERCENT.index, true ); + _style_4 = createHeaderStyle(wb); + } + + private static HSSFCellStyle createStyle(HSSFWorkbook wb, short h_align, short color, + boolean bold) { + HSSFFont font = wb.createFont(); + if (bold) { + font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); + } + + HSSFCellStyle cellStyle = wb.createCellStyle(); + cellStyle.setFont(font); + cellStyle.setFillForegroundColor(color); + cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); + cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); + cellStyle.setAlignment(h_align); + cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); + cellStyle.setLeftBorderColor(HSSFColor.BLACK.index); + cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); + cellStyle.setTopBorderColor(HSSFColor.BLACK.index); + cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); + cellStyle.setRightBorderColor(HSSFColor.BLACK.index); + cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); + cellStyle.setBottomBorderColor(HSSFColor.BLACK.index); + + return cellStyle; + } + + private static HSSFCellStyle createStyle(HSSFWorkbook wb, short h_align) { + return createStyle(wb, h_align, HSSFColor.WHITE.index, false); + } + private static HSSFCellStyle createHeaderStyle(HSSFWorkbook wb) { + HSSFFont font = wb.createFont(); + font.setColor( HSSFColor.WHITE.index ); + font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); + + HSSFCellStyle cellStyle = wb.createCellStyle(); + cellStyle.setFillForegroundColor(HSSFColor.BLUE_GREY.index); + cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); + cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); + cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); + cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); + cellStyle.setLeftBorderColor(HSSFColor.WHITE.index); + cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); + cellStyle.setTopBorderColor(HSSFColor.WHITE.index); + cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); + cellStyle.setRightBorderColor(HSSFColor.WHITE.index); + cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); + cellStyle.setBottomBorderColor(HSSFColor.WHITE.index); + cellStyle.setFont(font); + return cellStyle; + } + + + public HSSFSheet createSheet(String sheetName) { + _currentSheet = _wb.createSheet(sheetName); + return _currentSheet; + } + public void createDVTypeRow(String strTypeDescription) { + HSSFSheet sheet = _currentSheet; + HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows()); + row = sheet.createRow(sheet.getPhysicalNumberOfRows()); + sheet.addMergedRegion(new Region((short) (sheet.getPhysicalNumberOfRows() - 1), + (short) 0, (short) (sheet.getPhysicalNumberOfRows() - 1), (short) 5)); + HSSFCell cell = row.createCell((short) 0); + setCellValue(cell, strTypeDescription); + cell.setCellStyle(_style_3); + row = sheet.createRow(sheet.getPhysicalNumberOfRows()); + } + + public void createHeaderRow() { + HSSFSheet sheet = _currentSheet; + HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows()); + row.setHeight((short) 400); + for (int i = 0; i < 6; i++) { + row.createCell((short) i).setCellStyle(_style_4); + if (i == 2 || i == 3 || i == 4) { + sheet.setColumnWidth((short) i, (short) 3500); + } else if (i == 5) { + sheet.setColumnWidth((short) i, (short) 10000); + } else { + sheet.setColumnWidth((short) i, (short) 8000); + } + } + HSSFCell cell = row.getCell((short) 0); + setCellValue(cell, "Data validation cells"); + cell = row.getCell((short) 1); + setCellValue(cell, "Condition"); + cell = row.getCell((short) 2); + setCellValue(cell, "Allow blank"); + cell = row.getCell((short) 3); + setCellValue(cell, "Prompt box"); + cell = row.getCell((short) 4); + setCellValue(cell, "Error box"); + cell = row.getCell((short) 5); + setCellValue(cell, "Other settings"); + } + + public ValidationAdder createValidationAdder(HSSFCellStyle cellStyle, int dataValidationType) { + return new ValidationAdder(_currentSheet, _style_1, _style_2, cellStyle, dataValidationType); + } + + public void createDVDescriptionRow(String strTypeDescription) { + HSSFSheet sheet = _currentSheet; + HSSFRow row = sheet.getRow(sheet.getPhysicalNumberOfRows()-1); + sheet.addMergedRegion(new Region((short)(sheet.getPhysicalNumberOfRows()-1),(short)0,(short)(sheet.getPhysicalNumberOfRows()-1),(short)5)); + HSSFCell cell = row.createCell((short)0); + setCellValue(cell, strTypeDescription); + cell.setCellStyle(_style_3); + row = sheet.createRow(sheet.getPhysicalNumberOfRows()); + } + } + + + private void addCustomValidations(WorkbookFormatter wf) { + wf.createSheet("Custom"); + wf.createHeaderRow(); + + ValidationAdder va = wf.createValidationAdder(null, VT.FORMULA); + va.addValidation(OP.BETWEEN, "ISNUMBER($A2)", null, ES.STOP, "ISNUMBER(A2)", "Error box type = STOP", true, true, true); + va.addValidation(OP.BETWEEN, "IF(SUM(A2:A3)=5,TRUE,FALSE)", null, ES.WARNING, "IF(SUM(A2:A3)=5,TRUE,FALSE)", "Error box type = WARNING", false, false, true); + } + + private static void addSimpleNumericValidations(WorkbookFormatter wf) { + // data validation's number types + wf.createSheet("Numbers"); + + // "Whole number" validation type + wf.createDVTypeRow("Whole number"); + wf.createHeaderRow(); + + ValidationAdder va = wf.createValidationAdder(null, VT.INTEGER); + va.addValidation(OP.BETWEEN, "2", "6", ES.STOP, "Between 2 and 6 ", "Error box type = STOP", true, true, true); + va.addValidation(OP.NOT_BETWEEN, "2", "6", ES.INFO, "Not between 2 and 6 ", "Error box type = INFO", false, true, true); + va.addValidation(OP.EQUAL, "=3+2", null, ES.WARNING, "Equal to (3+2)", "Error box type = WARNING", false, false, true); + va.addValidation(OP.NOT_EQUAL, "3", null, ES.WARNING, "Not equal to 3", "-", false, false, false); + va.addValidation(OP.GREATER_THAN, "3", null, ES.WARNING, "Greater than 3", "-", true, false, false); + va.addValidation(OP.LESS_THAN, "3", null, ES.WARNING, "Less than 3", "-", true, true, false); + va.addValidation(OP.GREATER_OR_EQUAL, "4", null, ES.STOP, "Greater than or equal to 4", "Error box type = STOP", true, false, true); + va.addValidation(OP.LESS_OR_EQUAL, "4", null, ES.STOP, "Less than or equal to 4", "-", false, true, false); + + // "Decimal" validation type + wf.createDVTypeRow("Decimal"); + wf.createHeaderRow(); + + va = wf.createValidationAdder(null, VT.DECIMAL); + va.addValidation(OP.BETWEEN, "2", "6", ES.STOP, "Between 2 and 6 ", "Error box type = STOP", true, true, true); + va.addValidation(OP.NOT_BETWEEN, "2", "6", ES.INFO, "Not between 2 and 6 ", "Error box type = INFO", false, true, true); + va.addValidation(OP.EQUAL, "3", null, ES.WARNING, "Equal to 3", "Error box type = WARNING", false, false, true); + va.addValidation(OP.NOT_EQUAL, "3", null, ES.WARNING, "Not equal to 3", "-", false, false, false); + va.addValidation(OP.GREATER_THAN, "=12/6", null, ES.WARNING, "Greater than (12/6)", "-", true, false, false); + va.addValidation(OP.LESS_THAN, "3", null, ES.WARNING, "Less than 3", "-", true, true, false); + va.addValidation(OP.GREATER_OR_EQUAL, "4", null, ES.STOP, "Greater than or equal to 4", "Error box type = STOP", true, false, true); + va.addValidation(OP.LESS_OR_EQUAL, "4", null, ES.STOP, "Less than or equal to 4", "-", false, true, false); + } + + private static void addListValidations(WorkbookFormatter wf, HSSFWorkbook wb) { + final String cellStrValue + = "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 " + + "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 " + + "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 " + + "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "; + final String dataSheetName = "list_data"; + // "List" Data Validation type + HSSFSheet fSheet = wf.createSheet("Lists"); + HSSFSheet dataSheet = wb.createSheet(dataSheetName); + + + wf.createDVTypeRow("Explicit lists - list items are explicitly provided"); + wf.createDVDescriptionRow("Disadvantage - sum of item's length should be less than 255 characters"); + wf.createHeaderRow(); + + ValidationAdder va = wf.createValidationAdder(null, VT.LIST); + String listValsDescr = "POIFS,HSSF,HWPF,HPSF"; + String[] listVals = listValsDescr.split(","); + va.addListValidation(listVals, null, listValsDescr, false, false); + va.addListValidation(listVals, null, listValsDescr, false, true); + va.addListValidation(listVals, null, listValsDescr, true, false); + va.addListValidation(listVals, null, listValsDescr, true, true); + + + + wf.createDVTypeRow("Reference lists - list items are taken from others cells"); + wf.createDVDescriptionRow("Advantage - no restriction regarding the sum of item's length"); + wf.createHeaderRow(); + va = wf.createValidationAdder(null, VT.LIST); + String strFormula = "$A$30:$A$39"; + va.addListValidation(null, strFormula, strFormula, false, false); + + strFormula = dataSheetName + "!$A$1:$A$10"; + va.addListValidation(null, strFormula, strFormula, false, false); + HSSFName namedRange = wb.createName(); + namedRange.setNameName("myName"); + namedRange.setReference(dataSheetName + "!$A$2:$A$7"); + strFormula = "myName"; + va.addListValidation(null, strFormula, strFormula, false, false); + strFormula = "offset(myName, 2, 1, 4, 2)"; // Note about last param '2': + // - Excel expects single row or single column when entered in UI, but process this OK otherwise + va.addListValidation(null, strFormula, strFormula, false, false); + + // add list data on same sheet + for (int i = 0; i < 10; i++) { + HSSFRow currRow = fSheet.createRow(i + 29); + setCellValue(currRow.createCell((short) 0), cellStrValue); + } + // add list data on another sheet + for (int i = 0; i < 10; i++) { + HSSFRow currRow = dataSheet.createRow(i + 0); + setCellValue(currRow.createCell((short) 0), "Data a" + i); + setCellValue(currRow.createCell((short) 1), "Data b" + i); + setCellValue(currRow.createCell((short) 2), "Data c" + i); + } + } + + private static void addDateTimeValidations(WorkbookFormatter wf, HSSFWorkbook wb) { + wf.createSheet("Dates and Times"); + + HSSFDataFormat dataFormat = wb.createDataFormat(); + short fmtDate = dataFormat.getFormat("m/d/yyyy"); + short fmtTime = dataFormat.getFormat("h:mm"); + HSSFCellStyle cellStyle_date = wb.createCellStyle(); + cellStyle_date.setDataFormat(fmtDate); + HSSFCellStyle cellStyle_time = wb.createCellStyle(); + cellStyle_time.setDataFormat(fmtTime); + + wf.createDVTypeRow("Date ( cells are already formated as date - m/d/yyyy)"); + wf.createHeaderRow(); + + ValidationAdder va = wf.createValidationAdder(cellStyle_date, VT.DATE); + va.addValidation(OP.BETWEEN, "2004/01/02", "2004/01/06", ES.STOP, "Between 1/2/2004 and 1/6/2004 ", "Error box type = STOP", true, true, true); + va.addValidation(OP.NOT_BETWEEN, "2004/01/01", "2004/01/06", ES.INFO, "Not between 1/2/2004 and 1/6/2004 ", "Error box type = INFO", false, true, true); + va.addValidation(OP.EQUAL, "2004/03/02", null, ES.WARNING, "Equal to 3/2/2004", "Error box type = WARNING", false, false, true); + va.addValidation(OP.NOT_EQUAL, "2004/03/02", null, ES.WARNING, "Not equal to 3/2/2004", "-", false, false, false); + va.addValidation(OP.GREATER_THAN,"=DATEVALUE(\"4-Jul-2001\")", null, ES.WARNING, "Greater than DATEVALUE('4-Jul-2001')", "-", true, false, false); + va.addValidation(OP.LESS_THAN, "2004/03/02", null, ES.WARNING, "Less than 3/2/2004", "-", true, true, false); + va.addValidation(OP.GREATER_OR_EQUAL, "2004/03/02", null, ES.STOP, "Greater than or equal to 3/2/2004", "Error box type = STOP", true, false, true); + va.addValidation(OP.LESS_OR_EQUAL, "2004/03/04", null, ES.STOP, "Less than or equal to 3/4/2004", "-", false, true, false); + + // "Time" validation type + wf.createDVTypeRow("Time ( cells are already formated as time - h:mm)"); + wf.createHeaderRow(); + + va = wf.createValidationAdder(cellStyle_time, VT.TIME); + va.addValidation(OP.BETWEEN, "12:00", "16:00", ES.STOP, "Between 12:00 and 16:00 ", "Error box type = STOP", true, true, true); + va.addValidation(OP.NOT_BETWEEN, "12:00", "16:00", ES.INFO, "Not between 12:00 and 16:00 ", "Error box type = INFO", false, true, true); + va.addValidation(OP.EQUAL, "13:35", null, ES.WARNING, "Equal to 13:35", "Error box type = WARNING", false, false, true); + va.addValidation(OP.NOT_EQUAL, "13:35", null, ES.WARNING, "Not equal to 13:35", "-", false, false, false); + va.addValidation(OP.GREATER_THAN,"12:00", null, ES.WARNING, "Greater than 12:00", "-", true, false, false); + va.addValidation(OP.LESS_THAN, "=1/2", null, ES.WARNING, "Less than (1/2) -> 12:00", "-", true, true, false); + va.addValidation(OP.GREATER_OR_EQUAL, "14:00", null, ES.STOP, "Greater than or equal to 14:00", "Error box type = STOP", true, false, true); + va.addValidation(OP.LESS_OR_EQUAL,"14:00", null, ES.STOP, "Less than or equal to 14:00", "-", false, true, false); + } + + private static void addTextLengthValidations(WorkbookFormatter wf) { + wf.createSheet("Text lengths"); + wf.createHeaderRow(); + + ValidationAdder va = wf.createValidationAdder(null, VT.TEXT_LENGTH); + va.addValidation(OP.BETWEEN, "2", "6", ES.STOP, "Between 2 and 6 ", "Error box type = STOP", true, true, true); + va.addValidation(OP.NOT_BETWEEN, "2", "6", ES.INFO, "Not between 2 and 6 ", "Error box type = INFO", false, true, true); + va.addValidation(OP.EQUAL, "3", null, ES.WARNING, "Equal to 3", "Error box type = WARNING", false, false, true); + va.addValidation(OP.NOT_EQUAL, "3", null, ES.WARNING, "Not equal to 3", "-", false, false, false); + va.addValidation(OP.GREATER_THAN, "3", null, ES.WARNING, "Greater than 3", "-", true, false, false); + va.addValidation(OP.LESS_THAN, "3", null, ES.WARNING, "Less than 3", "-", true, true, false); + va.addValidation(OP.GREATER_OR_EQUAL, "4", null, ES.STOP, "Greater than or equal to 4", "Error box type = STOP", true, false, true); + va.addValidation(OP.LESS_OR_EQUAL, "4", null, ES.STOP, "Less than or equal to 4", "-", false, true, false); + } + + public void testDataValidation() { + log("\nTest no. 2 - Test Excel's Data validation mechanism"); + HSSFWorkbook wb = new HSSFWorkbook(); + WorkbookFormatter wf = new WorkbookFormatter(wb); + + log(" Create sheet for Data Validation's number types ... "); + addSimpleNumericValidations(wf); + log("done !"); + + log(" Create sheet for 'List' Data Validation type ... "); + addListValidations(wf, wb); + log("done !"); + + log(" Create sheet for 'Date' and 'Time' Data Validation types ... "); + addDateTimeValidations(wf, wb); + log("done !"); + + log(" Create sheet for 'Text length' Data Validation type... "); + addTextLengthValidations(wf); + log("done !"); + + // Custom Validation type + log(" Create sheet for 'Custom' Data Validation type ... "); + addCustomValidations(wf); + log("done !"); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(22000); + try { + wb.write(baos); + baos.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + byte[] generatedContent = baos.toByteArray(); + boolean isSame; + if (false) { + // TODO - add proof spreadsheet and compare + InputStream proofStream = HSSFTestDataSamples.openSampleFileStream("TestDataValidation.xls"); + isSame = compareStreams(proofStream, generatedContent); + } + isSame = true; + + if (isSame) { + return; + } + File tempDir = new File(System.getProperty("java.io.tmpdir")); + File generatedFile = new File(tempDir, "GeneratedTestDataValidation.xls"); + try { + FileOutputStream fileOut = new FileOutputStream(generatedFile); + fileOut.write(generatedContent); + fileOut.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + PrintStream ps = System.out; + + ps.println("This test case has failed because the generated file differs from proof copy '" + ); // TODO+ proofFile.getAbsolutePath() + "'."); + ps.println("The cause is usually a change to this test, or some common spreadsheet generation code. " + + "The developer has to decide whether the changes were wanted or unwanted."); + ps.println("If the changes to the generated version were unwanted, " + + "make the fix elsewhere (do not modify this test or the proof spreadsheet to get the test working)."); + ps.println("If the changes were wanted, make sure to open the newly generated file in Excel " + + "and verify it manually. The new proof file should be submitted after it is verified to be correct."); + ps.println(""); + ps.println("One other possible (but less likely) cause of a failed test is a problem in the " + + "comparison logic used here. Perhaps some extra file regions need to be ignored."); + ps.println("The generated file has been saved to '" + generatedFile.getAbsolutePath() + "' for manual inspection."); + + fail("Generated file differs from proof copy. See sysout comments for details on how to fix."); + + } + + private static boolean compareStreams(InputStream isA, byte[] generatedContent) { + + InputStream isB = new ByteArrayInputStream(generatedContent); + + // The allowable regions where the generated file can differ from the + // proof should be small (i.e. much less than 1K) + int[] allowableDifferenceRegions = { + 0x0228, 16, // a region of the file containing the OS username + 0x506C, 8, // See RootProperty (super fields _seconds_2 and _days_2) + }; + int[] diffs = StreamUtility.diffStreams(isA, isB, allowableDifferenceRegions); + if (diffs == null) { + return true; + } + System.err.println("Diff from proof: "); + for (int i = 0; i < diffs.length; i++) { + System.err.println("diff at offset: 0x" + Integer.toHexString(diffs[i])); + } + return false; + } + + + + + + /* package */ static void setCellValue(HSSFCell cell, String text) { + cell.setCellValue(new HSSFRichTextString(text)); + } - - private void createDVTypeRow( HSSFWorkbook wb, int sheetNo , HSSFCellStyle cellStyle, String strTypeDescription) - { - HSSFSheet sheet = wb.getSheetAt(sheetNo); - HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows()); - row = sheet.createRow(sheet.getPhysicalNumberOfRows()); - sheet.addMergedRegion(new Region((short)(sheet.getPhysicalNumberOfRows()-1),(short)0,(short)(sheet.getPhysicalNumberOfRows()-1),(short)5)); - HSSFCell cell = row.createCell((short)0); - cell.setCellValue(strTypeDescription); - cell.setCellStyle(cellStyle); - row = sheet.createRow(sheet.getPhysicalNumberOfRows()); - } - - private void createDVDeescriptionRow( HSSFWorkbook wb, int sheetNo , HSSFCellStyle cellStyle, String strTypeDescription ) - { - HSSFSheet sheet = wb.getSheetAt(sheetNo); - HSSFRow row = sheet.getRow(sheet.getPhysicalNumberOfRows()-1); - sheet.addMergedRegion(new Region((short)(sheet.getPhysicalNumberOfRows()-1),(short)0,(short)(sheet.getPhysicalNumberOfRows()-1),(short)5)); - HSSFCell cell = row.createCell((short)0); - cell.setCellValue(strTypeDescription); - cell.setCellStyle(cellStyle); - row = sheet.createRow(sheet.getPhysicalNumberOfRows()); - } - - private void createHeaderRow( HSSFWorkbook wb, int sheetNo , HSSFCellStyle cellStyle ) - { - HSSFSheet sheet = wb.getSheetAt(sheetNo); - HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows()); - row.setHeight((short)400); - for ( int i=0; i<6; i++ ) - { - row.createCell((short)i).setCellStyle( cellStyle ); - if ( i==2 || i==3 || i==4 ) - { - sheet.setColumnWidth( (short) i, (short) 3500); - } - else if ( i== 5) - { - sheet.setColumnWidth( (short) i, (short) 10000); - } - else - { - sheet.setColumnWidth( (short) i, (short) 8000); - } - } - HSSFCell cell = row.getCell((short)0); - cell.setCellValue("Data validation cells"); - cell = row.getCell((short)1); - cell.setCellValue("Condition"); - cell = row.getCell((short)2); - cell.setCellValue("Allow blank"); - cell = row.getCell((short)3); - cell.setCellValue("Prompt box"); - cell = row.getCell((short)4); - cell.setCellValue("Error box"); - cell = row.getCell((short)5); - cell.setCellValue("Other settings"); - } - - private HSSFCellStyle createHeaderStyle(HSSFWorkbook wb) - { - HSSFFont font = wb.createFont(); - font.setColor( HSSFColor.WHITE.index ); - font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); - - HSSFCellStyle cellStyle = wb.createCellStyle(); - cellStyle.setFillForegroundColor(HSSFColor.BLUE_GREY.index); - cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); - cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); - cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); - cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); - cellStyle.setLeftBorderColor(HSSFColor.WHITE.index); - cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); - cellStyle.setTopBorderColor(HSSFColor.WHITE.index); - cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); - cellStyle.setRightBorderColor(HSSFColor.WHITE.index); - cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); - cellStyle.setBottomBorderColor(HSSFColor.WHITE.index); - cellStyle.setFont(font); - return cellStyle; - } - - private HSSFCellStyle createStyle( HSSFWorkbook wb, short h_align, short color, boolean bold ) - { - HSSFFont font = wb.createFont(); - if ( bold ) - { - font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); - } - - HSSFCellStyle cellStyle = wb.createCellStyle(); - cellStyle.setFont(font); - cellStyle.setFillForegroundColor(color); - cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); - cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); - cellStyle.setAlignment(h_align); - cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); - cellStyle.setLeftBorderColor(HSSFColor.BLACK.index); - cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); - cellStyle.setTopBorderColor(HSSFColor.BLACK.index); - cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); - cellStyle.setRightBorderColor(HSSFColor.BLACK.index); - cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); - cellStyle.setBottomBorderColor(HSSFColor.BLACK.index); - - return cellStyle; - } - - private HSSFCellStyle createStyle( HSSFWorkbook wb, short h_align ) - { - return this.createStyle(wb, h_align, HSSFColor.WHITE.index, false); - } - - private void writeDataValidationSettings( HSSFSheet sheet, HSSFCellStyle style_1, HSSFCellStyle style_2, String strCondition, boolean allowEmpty, boolean inputBox, boolean errorBox ) - { - HSSFRow row = sheet.createRow( sheet.getPhysicalNumberOfRows() ); - //condition's string - HSSFCell cell = row.createCell((short)1); - cell.setCellStyle(style_1); - cell.setCellValue(strCondition); - //allow empty cells - cell = row.createCell((short)2); - cell.setCellStyle(style_2); - cell.setCellValue( ((allowEmpty) ? "yes" : "no") ); - //show input box - cell = row.createCell((short)3); - cell.setCellStyle(style_2); - cell.setCellValue( ((inputBox) ? "yes" : "no") ); - //show error box - cell = row.createCell((short)4); - cell.setCellStyle(style_2); - cell.setCellValue( ((errorBox) ? "yes" : "no") ); - } - - private void setCellFormat( HSSFSheet sheet, HSSFCellStyle cell_style ) - { - HSSFRow row = sheet.getRow( sheet.getPhysicalNumberOfRows() -1 ); - HSSFCell cell = row.createCell((short)0); - cell.setCellStyle(cell_style); - } - - private void writeOtherSettings( HSSFSheet sheet, HSSFCellStyle style, String strStettings ) - { - HSSFRow row = sheet.getRow( sheet.getPhysicalNumberOfRows() -1 ); - HSSFCell cell = row.createCell((short)5); - cell.setCellStyle(style); - cell.setCellValue(strStettings); - } - public void testAddToExistingSheet() { @@ -913,19 +574,32 @@ public class TestDataValidation extends TestCase int dvRow = 0; HSSFSheet sheet = wb.getSheetAt(0); sheet.createRow(dvRow).createCell((short)0); - HSSFDataValidation dv = new HSSFDataValidation((short)dvRow, (short)0, (short)dvRow, (short)0); + DVConstraint dc = DVConstraint.createNumericConstraint(VT.INTEGER, OP.EQUAL, "402", null); + HSSFDataValidation dv = new HSSFDataValidation(new CellRangeAddressList(dvRow, 0, dvRow, 0), dc); + - dv.setDataValidationType(HSSFDataValidation.DATA_TYPE_INTEGER); dv.setEmptyCellAllowed(false); - dv.setOperator(HSSFDataValidation.OPERATOR_EQUAL); - dv.setFirstFormula("42"); - dv.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP); + dv.setErrorStyle(ES.STOP); dv.setShowPromptBox(true); dv.createErrorBox("Error", "The value is wrong"); - dv.setSurppressDropDownArrow(true); + dv.setSuppressDropDownArrow(true); + + // sheet.addValidationData(dv); + + + dc = DVConstraint.createNumericConstraint(VT.INTEGER, OP.EQUAL, "42", null); + dv = new HSSFDataValidation(new CellRangeAddressList(0, 0, 0, 0), dc); + + + dv.setEmptyCellAllowed(false); + dv.setErrorStyle(ES.STOP); + dv.setShowPromptBox(true); + dv.createErrorBox("Xxx", "Yyy"); + dv.setSuppressDropDownArrow(true); sheet.addValidationData(dv); - wb.toString(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { @@ -963,9 +637,22 @@ public class TestDataValidation extends TestCase // and the DV records, Excel will not be able to open the workbook without error. if (nextSid == 0x0867) { - throw new AssertionFailedError("Identified bug 45519"); + throw new AssertionFailedError("Identified bug XXXX"); } assertEquals(DVRecord.sid, nextSid); + + + + File tempDir = new File("c:/josh/temp"); + File generatedFile = new File(tempDir, "dvEx2.xls"); + try { + FileOutputStream fileOut = new FileOutputStream(generatedFile); + wb.write(fileOut); + fileOut.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } private int findIndex(byte[] largeData, byte[] searchPattern) { byte firstByte = searchPattern[0]; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java index 894c77d685..4fce0af1d3 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java @@ -39,7 +39,7 @@ import org.apache.poi.hssf.model.Workbook; * @author Alex Jacoby (ajacoby at gmail.com) * @version %I%, %G% */ -public class TestHSSFDateUtil extends TestCase { +public final class TestHSSFDateUtil extends TestCase { public static final int CALENDAR_JANUARY = 0; public static final int CALENDAR_FEBRUARY = 1; @@ -47,11 +47,6 @@ public class TestHSSFDateUtil extends TestCase { public static final int CALENDAR_APRIL = 3; public static final int CALENDAR_JULY = 6; public static final int CALENDAR_OCTOBER = 9; - - public TestHSSFDateUtil(String s) - { - super(s); - } /** * Checks the date conversion functions in the HSSFDateUtil class. @@ -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() { GregorianCalendar date = new GregorianCalendar(2002, 0, 1, 12, 1, 1); Date expected = date.getTime(); - double expectedExcel = HSSFDateUtil.getExcelDate(expected); - // Iteratating over the hours exposes any rounding issues. + // Iterating over the hours exposes any rounding issues. for (int hour = -12; hour <= 12; hour++) { String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00"; @@ -209,7 +203,7 @@ public class TestHSSFDateUtil extends TestCase { double excelDate = HSSFDateUtil.getExcelDate(date, false); Date javaDate = HSSFDateUtil.getJavaDate(excelDate); - // Should match despite timezone + // Should match despite time-zone assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime()); } } @@ -402,7 +396,11 @@ public class TestHSSFDateUtil extends TestCase { assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), true), 0.00001); } - private Date createDate(int year, int month, int day) { + /** + * @param month zero based + * @param day one based + */ + private static Date createDate(int year, int month, int day) { Calendar c = new GregorianCalendar(); c.set(year, month, day, 0, 0, 0); c.set(Calendar.MILLISECOND, 0); @@ -420,10 +418,18 @@ public class TestHSSFDateUtil extends TestCase { calendar = new GregorianCalendar(1901, 0, 1); assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false)); } + + public void testConvertTime() { + + final double delta = 1E-7; // a couple of digits more accuracy than strictly required + assertEquals(0.5, HSSFDateUtil.convertTime("12:00"), delta); + assertEquals(2.0/3, HSSFDateUtil.convertTime("16:00"), delta); + assertEquals(0.0000116, HSSFDateUtil.convertTime("0:00:01"), delta); + assertEquals(0.7330440, HSSFDateUtil.convertTime("17:35:35"), delta); + } - public static void main(String [] args) { - System.out - .println("Testing org.apache.poi.hssf.usermodel.TestHSSFDateUtil"); - junit.textui.TestRunner.run(TestHSSFDateUtil.class); + public void testParseDate() { + assertEquals(createDate(2008, Calendar.AUGUST, 3), HSSFDateUtil.parseYYYYMMDDDate("2008/08/03")); + assertEquals(createDate(1994, Calendar.MAY, 1), HSSFDateUtil.parseYYYYMMDDDate("1994/05/01")); } }