Browse Source

support for data validation for OOXML, see Bugzilla 49244

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@944869 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_7_BETA1
Yegor Kozlov 14 years ago
parent
commit
afe2ad7d38

+ 1
- 0
src/documentation/content/xdocs/status.xml View File

@@ -34,6 +34,7 @@

<changes>
<release version="3.7-SNAPSHOT" date="2010-??-??">
<action dev="POI-DEVELOPERS" type="add">49244 -Support for data validation for OOXML format</action>
<action dev="POI-DEVELOPERS" type="add">49066 - Worksheet/cell formatting, with view and HTML converter</action>
<action dev="POI-DEVELOPERS" type="fix">49020 - Workaround Excel outputting invalid XML in button definitions by not closing BR tags</action>
<action dev="POI-DEVELOPERS" type="fix">49050 - Improve performance of AbstractEscherHolderRecord when there are lots of Continue Records</action>

+ 79
- 131
src/java/org/apache/poi/hssf/usermodel/DVConstraint.java View File

@@ -26,68 +26,14 @@ import org.apache.poi.hssf.record.formula.NumberPtg;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.StringPtg;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.usermodel.DataValidationConstraint;

/**
*
* @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 {
public class DVConstraint implements DataValidationConstraint {
/* package */ public static final class FormulaPair {

private final Ptg[] _formula1;
private final Ptg[] _formula2;
@@ -211,8 +157,8 @@ public class DVConstraint {
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
@@ -321,65 +267,8 @@ public class DVConstraint {
return new DVConstraint(VT.FORMULA, OperatorType.IGNORED, formula, null, null, null, null);
}
/**
* @return both parsed formulas (for expression 1 and 2).
*/
/* package */ FormulaPair createFormulas(HSSFSheet sheet) {
Ptg[] formula1;
Ptg[] formula2;
if (isListValidationType()) {
formula1 = createListFormula(sheet);
formula2 = Ptg.EMPTY_PTG_ARRAY;
} else {
formula1 = convertDoubleFormula(_formula1, _value1, sheet);
formula2 = convertDoubleFormula(_formula2, _value2, sheet);
}
return new FormulaPair(formula1, formula2);
}

private Ptg[] createListFormula(HSSFSheet sheet) {

if (_explicitListValues == null) {
HSSFWorkbook wb = sheet.getWorkbook();
// formula is parsed with slightly different RVA rules: (root node type must be 'reference')
return HSSFFormulaParser.parse(_formula1, wb, FormulaType.DATAVALIDATION_LIST, wb.getSheetIndex(sheet));
// To do: Excel places restrictions on the available operations within a list formula.
// Some things like union and intersection are not allowed.
}
// explicit list was provided
StringBuffer sb = new StringBuffer(_explicitListValues.length * 16);
for (int i = 0; i < _explicitListValues.length; i++) {
if (i > 0) {
sb.append('\0'); // list delimiter is the nul char
}
sb.append(_explicitListValues[i]);
}
return new Ptg[] { new StringPtg(sb.toString()), };
}

/**
* @return The parsed token array representing the formula or value specified.
* Empty array if both formula and value are <code>null</code>
*/
private static Ptg[] convertDoubleFormula(String formula, Double value, HSSFSheet sheet) {
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");
}
HSSFWorkbook wb = sheet.getWorkbook();
return HSSFFormulaParser.parse(formula, wb, FormulaType.CELL, wb.getSheetIndex(sheet));
}
/**
* @return data validation type of this constraint
* @see ValidationType
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidationConstraint#getValidationType()
*/
public int getValidationType() {
return _validationType;
@@ -398,24 +287,28 @@ public class DVConstraint {
public boolean isExplicitList() {
return _validationType == VT.LIST && _explicitListValues != null;
}
/**
* @return the operator used for this constraint
* @see OperatorType
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidationConstraint#getOperator()
*/
public int getOperator() {
return _operator;
}
/**
* Sets the comparison operator for this constraint
* @see OperatorType
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidationConstraint#setOperator(int)
*/
public void setOperator(int operator) {
_operator = operator;
}
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidationConstraint#getExplicitListValues()
*/
public String[] getExplicitListValues() {
return _explicitListValues;
}
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidationConstraint#setExplicitListValues(java.lang.String[])
*/
public void setExplicitListValues(String[] explicitListValues) {
if (_validationType != VT.LIST) {
throw new RuntimeException("Cannot setExplicitListValues on non-list constraint");
@@ -424,14 +317,14 @@ public class DVConstraint {
_explicitListValues = explicitListValues;
}

/**
* @return the formula for expression 1. May be <code>null</code>
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidationConstraint#getFormula1()
*/
public String getFormula1() {
return _formula1;
}
/**
* Sets a formula for expression 1.
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidationConstraint#setFormula1(java.lang.String)
*/
public void setFormula1(String formula1) {
_value1 = null;
@@ -439,14 +332,14 @@ public class DVConstraint {
_formula1 = formula1;
}

/**
* @return the formula for expression 2. May be <code>null</code>
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidationConstraint#getFormula2()
*/
public String getFormula2() {
return _formula2;
}
/**
* Sets a formula for expression 2.
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidationConstraint#setFormula2(java.lang.String)
*/
public void setFormula2(String formula2) {
_value2 = null;
@@ -480,4 +373,59 @@ public class DVConstraint {
_formula2 = null;
_value2 = new Double(value2);
}
/**
* @return both parsed formulas (for expression 1 and 2).
*/
/* package */ FormulaPair createFormulas(HSSFSheet sheet) {
Ptg[] formula1;
Ptg[] formula2;
if (isListValidationType()) {
formula1 = createListFormula(sheet);
formula2 = Ptg.EMPTY_PTG_ARRAY;
} else {
formula1 = convertDoubleFormula(_formula1, _value1, sheet);
formula2 = convertDoubleFormula(_formula2, _value2, sheet);
}
return new FormulaPair(formula1, formula2);
}

private Ptg[] createListFormula(HSSFSheet sheet) {

if (_explicitListValues == null) {
HSSFWorkbook wb = sheet.getWorkbook();
// formula is parsed with slightly different RVA rules: (root node type must be 'reference')
return HSSFFormulaParser.parse(_formula1, wb, FormulaType.DATAVALIDATION_LIST, wb.getSheetIndex(sheet));
// To do: Excel places restrictions on the available operations within a list formula.
// Some things like union and intersection are not allowed.
}
// explicit list was provided
StringBuffer sb = new StringBuffer(_explicitListValues.length * 16);
for (int i = 0; i < _explicitListValues.length; i++) {
if (i > 0) {
sb.append('\0'); // list delimiter is the nul char
}
sb.append(_explicitListValues[i]);
}
return new Ptg[] { new StringPtg(sb.toString()), };
}

/**
* @return The parsed token array representing the formula or value specified.
* Empty array if both formula and value are <code>null</code>
*/
private static Ptg[] convertDoubleFormula(String formula, Double value, HSSFSheet sheet) {
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");
}
HSSFWorkbook wb = sheet.getWorkbook();
return HSSFFormulaParser.parse(formula, wb, FormulaType.CELL, wb.getSheetIndex(sheet));
}
}

+ 55
- 83
src/java/org/apache/poi/hssf/usermodel/HSSFDataValidation.java View File

@@ -19,6 +19,9 @@ 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.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType;
import org.apache.poi.ss.util.CellRangeAddressList;

/**
@@ -26,19 +29,7 @@ import org.apache.poi.ss.util.CellRangeAddressList;
*
* @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;
}

public final class HSSFDataValidation implements DataValidation {
private String _prompt_title;
private String _prompt_text;
private String _error_title;
@@ -49,7 +40,7 @@ public final class HSSFDataValidation {
private boolean _suppress_dropdown_arrow = false;
private boolean _showPromptBox = true;
private boolean _showErrorBox = true;
private final CellRangeAddressList _regions;
private CellRangeAddressList _regions;
private DVConstraint _constraint;

/**
@@ -57,119 +48,106 @@ public final class HSSFDataValidation {
* applied
* @param constraint
*/
public HSSFDataValidation(CellRangeAddressList regions, DVConstraint constraint) {
public HSSFDataValidation(CellRangeAddressList regions, DataValidationConstraint constraint) {
_regions = regions;
_constraint = constraint;
//FIXME: This cast can be avoided.
_constraint = (DVConstraint)constraint;
}


/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getConstraint()
*/
public DataValidationConstraint getValidationConstraint() {
return _constraint;
}

public DVConstraint getConstraint() {
return _constraint;
}
public CellRangeAddressList getRegions() {
return _regions;
}

/**
* Sets the error style for error box
* @see ErrorStyle
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#setErrorStyle(int)
*/
public void setErrorStyle(int error_style) {
_errorStyle = error_style;
}

/**
* @return the error style of error box
* @see ErrorStyle
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getErrorStyle()
*/
public int getErrorStyle() {
return _errorStyle;
}

/**
* Sets if this object allows empty as a valid value
*
* @param allowed <code>true</code> if this object should treats empty as valid value , <code>false</code>
* otherwise
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#setEmptyCellAllowed(boolean)
*/
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
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getEmptyCellAllowed()
*/
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
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#setSuppressDropDownArrow(boolean)
*/
public void setSuppressDropDownArrow(boolean suppress) {
_suppress_dropdown_arrow = suppress;
}

/**
* Useful only list validation objects . This method always returns false if
* the object isn't a list validation object
*
* @return <code>true</code> if a list should display the values into a drop down list ,
* <code>false</code> otherwise .
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getSuppressDropDownArrow()
*/
public boolean getSuppressDropDownArrow() {
if (_constraint.isListValidationType()) {
if (_constraint.getValidationType()==ValidationType.LIST) {
return _suppress_dropdown_arrow;
}
return false;
}

/**
* Sets the behaviour when a cell which belongs to this object is selected
*
* @param show <code>true</code> if an prompt box should be displayed , <code>false</code> otherwise
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#setShowPromptBox(boolean)
*/
public void setShowPromptBox(boolean show) {
_showPromptBox = show;
}

/**
* @return <code>true</code> if an prompt box should be displayed , <code>false</code> otherwise
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getShowPromptBox()
*/
public boolean getShowPromptBox() {
return _showPromptBox;
}

/**
* Sets the behaviour when an invalid value is entered
*
* @param show <code>true</code> if an error box should be displayed , <code>false</code> otherwise
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#setShowErrorBox(boolean)
*/
public void setShowErrorBox(boolean show) {
_showErrorBox = show;
}

/**
* @return <code>true</code> if an error box should be displayed , <code>false</code> otherwise
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getShowErrorBox()
*/
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
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#createPromptBox(java.lang.String, java.lang.String)
*/
public void createPromptBox(String title, String text) {
_prompt_title = title;
@@ -177,28 +155,22 @@ public final class HSSFDataValidation {
this.setShowPromptBox(true);
}

/**
* @return Prompt box's title or <code>null</code>
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getPromptBoxTitle()
*/
public String getPromptBoxTitle() {
return _prompt_title;
}

/**
* @return Prompt box's text or <code>null</code>
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getPromptBoxText()
*/
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
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#createErrorBox(java.lang.String, java.lang.String)
*/
public void createErrorBox(String title, String text) {
_error_title = title;
@@ -206,15 +178,15 @@ public final class HSSFDataValidation {
this.setShowErrorBox(true);
}

/**
* @return Error box's title or <code>null</code>
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getErrorBoxTitle()
*/
public String getErrorBoxTitle() {
return _error_title;
}

/**
* @return Error box's text or <code>null</code>
/* (non-Javadoc)
* @see org.apache.poi.hssf.usermodel.DataValidation#getErrorBoxText()
*/
public String getErrorBoxText() {
return _error_text;
@@ -227,7 +199,7 @@ public final class HSSFDataValidation {
return new DVRecord(_constraint.getValidationType(),
_constraint.getOperator(),
_errorStyle, _emptyCellAllowed, getSuppressDropDownArrow(),
_constraint.isExplicitList(),
_constraint.getValidationType()==ValidationType.LIST && _constraint.getExplicitListValues()!=null,
_showPromptBox, _prompt_title, _prompt_text,
_showErrorBox, _error_title, _error_text,
fp.getFormula1(), fp.getFormula2(),

+ 118
- 0
src/java/org/apache/poi/hssf/usermodel/HSSFDataValidationHelper.java View File

@@ -0,0 +1,118 @@
/**
*
*/
package org.apache.poi.hssf.usermodel;

import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType;
import org.apache.poi.ss.util.CellRangeAddressList;

/**
* @author <a href="rjankiraman@emptoris.com">Radhakrishnan J</a>
*
*/
public class HSSFDataValidationHelper implements DataValidationHelper {
@SuppressWarnings("unused")
private HSSFSheet sheet;
public HSSFDataValidationHelper(HSSFSheet sheet) {
super();
this.sheet = sheet;
}

/*
* (non-Javadoc)
*
* @see
* org.apache.poi.ss.usermodel.DataValidationHelper#createDateConstraint
* (int, java.lang.String, java.lang.String, java.lang.String)
*/
public DataValidationConstraint createDateConstraint(int operatorType, String formula1, String formula2, String dateFormat) {
return DVConstraint.createDateConstraint(operatorType, formula1, formula2, dateFormat);
}

/*
* (non-Javadoc)
*
* @see
* org.apache.poi.ss.usermodel.DataValidationHelper#createExplicitListConstraint
* (java.lang.String[])
*/
public DataValidationConstraint createExplicitListConstraint(String[] listOfValues) {
return DVConstraint.createExplicitListConstraint(listOfValues);
}

/*
* (non-Javadoc)
*
* @see
* org.apache.poi.ss.usermodel.DataValidationHelper#createFormulaListConstraint
* (java.lang.String)
*/
public DataValidationConstraint createFormulaListConstraint(String listFormula) {
return DVConstraint.createFormulaListConstraint(listFormula);
}

public DataValidationConstraint createNumericConstraint(int validationType,int operatorType, String formula1, String formula2) {
return DVConstraint.createNumericConstraint(validationType, operatorType, formula1, formula2);
}

public DataValidationConstraint createIntegerConstraint(int operatorType, String formula1, String formula2) {
return DVConstraint.createNumericConstraint(ValidationType.INTEGER, operatorType, formula1, formula2);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.poi.ss.usermodel.DataValidationHelper#createNumericConstraint
* (int, java.lang.String, java.lang.String)
*/
public DataValidationConstraint createDecimalConstraint(int operatorType, String formula1, String formula2) {
return DVConstraint.createNumericConstraint(ValidationType.DECIMAL, operatorType, formula1, formula2);
}

/*
* (non-Javadoc)
*
* @see
* org.apache.poi.ss.usermodel.DataValidationHelper#createTextLengthConstraint
* (int, java.lang.String, java.lang.String)
*/
public DataValidationConstraint createTextLengthConstraint(int operatorType, String formula1, String formula2) {
return DVConstraint.createNumericConstraint(ValidationType.TEXT_LENGTH, operatorType, formula1, formula2);
}

/*
* (non-Javadoc)
*
* @see
* org.apache.poi.ss.usermodel.DataValidationHelper#createTimeConstraint
* (int, java.lang.String, java.lang.String, java.lang.String)
*/
public DataValidationConstraint createTimeConstraint(int operatorType, String formula1, String formula2) {
return DVConstraint.createTimeConstraint(operatorType, formula1, formula2);
}

public DataValidationConstraint createCustomConstraint(String formula) {
return DVConstraint.createCustomFormulaConstraint(formula);
}

/*
* (non-Javadoc)
*
* @see
* org.apache.poi.ss.usermodel.DataValidationHelper#createValidation(org
* .apache.poi.ss.usermodel.DataValidationConstraint,
* org.apache.poi.ss.util.CellRangeAddressList)
*/
public DataValidation createValidation(DataValidationConstraint constraint, CellRangeAddressList cellRangeAddressList) {
return new HSSFDataValidation(cellRangeAddressList, constraint);
}
}

+ 12
- 3
src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java View File

@@ -51,15 +51,17 @@ import org.apache.poi.hssf.record.formula.FormulaShifter;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellRange;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.SSCellRange;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

@@ -373,13 +375,14 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
* Creates a data validation object
* @param dataValidation The Data validation object settings
*/
public void addValidationData(HSSFDataValidation dataValidation) {
public void addValidationData(DataValidation dataValidation) {
if (dataValidation == null) {
throw new IllegalArgumentException("objValidation must not be null");
}
HSSFDataValidation hssfDataValidation = (HSSFDataValidation)dataValidation;
DataValidityTable dvt = _sheet.getOrCreateDataValidityTable();

DVRecord dvRecord = dataValidation.createDVRecord(this);
DVRecord dvRecord = hssfDataValidation.createDVRecord(this);
dvt.addDataValidation(dvRecord);
}

@@ -1997,4 +2000,10 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
}
return result;
}

public DataValidationHelper getDataValidationHelper() {
return new HSSFDataValidationHelper(this);
}
}

+ 152
- 0
src/java/org/apache/poi/ss/usermodel/DataValidation.java View File

@@ -0,0 +1,152 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.ss.usermodel;

import org.apache.poi.ss.util.CellRangeAddressList;


public interface DataValidation {
/**
* 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;
}

public abstract DataValidationConstraint getValidationConstraint();

/**
* Sets the error style for error box
* @see ErrorStyle
*/
public abstract void setErrorStyle(int error_style);

/**o
* @return the error style of error box
* @see ErrorStyle
*/
public abstract int getErrorStyle();

/**
* Sets if this object allows empty as a valid value
*
* @param allowed <code>true</code> if this object should treats empty as valid value , <code>false</code>
* otherwise
*/
public abstract void setEmptyCellAllowed(boolean allowed);

/**
* Retrieve the settings for empty cells allowed
*
* @return True if this object should treats empty as valid value , false
* otherwise
*/
public abstract boolean getEmptyCellAllowed();

/**
* 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 abstract void setSuppressDropDownArrow(boolean suppress);

/**
* Useful only list validation objects . This method always returns false if
* the object isn't a list validation object
*
* @return <code>true</code> if a list should display the values into a drop down list ,
* <code>false</code> otherwise .
*/
public abstract boolean getSuppressDropDownArrow();

/**
* Sets the behaviour when a cell which belongs to this object is selected
*
* @param show <code>true</code> if an prompt box should be displayed , <code>false</code> otherwise
*/
public abstract void setShowPromptBox(boolean show);

/**
* @return <code>true</code> if an prompt box should be displayed , <code>false</code> otherwise
*/
public abstract boolean getShowPromptBox();

/**
* Sets the behaviour when an invalid value is entered
*
* @param show <code>true</code> if an error box should be displayed , <code>false</code> otherwise
*/
public abstract void setShowErrorBox(boolean show);

/**
* @return <code>true</code> if an error box should be displayed , <code>false</code> otherwise
*/
public abstract boolean getShowErrorBox();

/**
* 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 abstract void createPromptBox(String title, String text);

/**
* @return Prompt box's title or <code>null</code>
*/
public abstract String getPromptBoxTitle();

/**
* @return Prompt box's text or <code>null</code>
*/
public abstract String getPromptBoxText();

/**
* 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 abstract void createErrorBox(String title, String text);

/**
* @return Error box's title or <code>null</code>
*/
public abstract String getErrorBoxTitle();

/**
* @return Error box's text or <code>null</code>
*/
public abstract String getErrorBoxText();

public abstract CellRangeAddressList getRegions();

}

+ 118
- 0
src/java/org/apache/poi/ss/usermodel/DataValidationConstraint.java View File

@@ -0,0 +1,118 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.ss.usermodel;


public interface DataValidationConstraint {

/**
* @return data validation type of this constraint
* @see ValidationType
*/
public abstract int getValidationType();

/**
* @return the operator used for this constraint
* @see OperatorType
*/
public abstract int getOperator();

/**
* Sets the comparison operator for this constraint
* @see OperatorType
*/
public abstract void setOperator(int operator);

public abstract String[] getExplicitListValues();

public abstract void setExplicitListValues(String[] explicitListValues);

/**
* @return the formula for expression 1. May be <code>null</code>
*/
public abstract String getFormula1();

/**
* Sets a formula for expression 1.
*/
public abstract void setFormula1(String formula1);

/**
* @return the formula for expression 2. May be <code>null</code>
*/
public abstract String getFormula2();

/**
* Sets a formula for expression 2.
*/
public abstract void setFormula2(String formula2);
/**
* 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 */ public 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
}
}
}
}

+ 46
- 0
src/java/org/apache/poi/ss/usermodel/DataValidationHelper.java View File

@@ -0,0 +1,46 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.ss.usermodel;

import org.apache.poi.ss.util.CellRangeAddressList;

/**
* @author <a href="rjankiraman@emptoris.com">Radhakrishnan J</a>
*
*/
public interface DataValidationHelper {
DataValidationConstraint createFormulaListConstraint(String listFormula);

DataValidationConstraint createExplicitListConstraint(String[] listOfValues);

DataValidationConstraint createNumericConstraint(int validationType,int operatorType, String formula1, String formula2);
DataValidationConstraint createTextLengthConstraint(int operatorType, String formula1, String formula2);
DataValidationConstraint createDecimalConstraint(int operatorType, String formula1, String formula2);
DataValidationConstraint createIntegerConstraint(int operatorType, String formula1, String formula2);
DataValidationConstraint createDateConstraint(int operatorType, String formula1, String formula2,String dateFormat);
DataValidationConstraint createTimeConstraint(int operatorType, String formula1, String formula2);
DataValidationConstraint createCustomConstraint(String formula);
DataValidation createValidation(DataValidationConstraint constraint,CellRangeAddressList cellRangeAddressList);
}

+ 8
- 0
src/java/org/apache/poi/ss/usermodel/Sheet.java View File

@@ -798,4 +798,12 @@ public interface Sheet extends Iterable<Row> {
* @return the {@link CellRange} of cells affected by this change
*/
CellRange<? extends Cell> removeArrayFormula(Cell cell);
public DataValidationHelper getDataValidationHelper();

/**
* Creates a data validation object
* @param dataValidation The Data validation object settings
*/
public void addValidationData(DataValidation dataValidation);
}

+ 244
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java View File

@@ -0,0 +1,244 @@
/**
*
*/
package org.apache.poi.xssf.usermodel;

import java.util.HashMap;
import java.util.Map;

import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidation;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationErrorStyle;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationOperator;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationType;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationOperator.Enum;

/**
* @author <a href="rjankiraman@emptoris.com">Radhakrishnan J</a>
*
*/
public class XSSFDataValidation implements DataValidation {
private CTDataValidation ctDdataValidation;
private XSSFDataValidationConstraint validationConstraint;
private CellRangeAddressList regions;

static Map<Integer,STDataValidationOperator.Enum> operatorTypeMappings = new HashMap<Integer,STDataValidationOperator.Enum>();
static Map<STDataValidationOperator.Enum,Integer> operatorTypeReverseMappings = new HashMap<STDataValidationOperator.Enum,Integer>();
static Map<Integer,STDataValidationType.Enum> validationTypeMappings = new HashMap<Integer,STDataValidationType.Enum>();
static Map<STDataValidationType.Enum,Integer> validationTypeReverseMappings = new HashMap<STDataValidationType.Enum,Integer>();
static Map<Integer,STDataValidationErrorStyle.Enum> errorStyleMappings = new HashMap<Integer,STDataValidationErrorStyle.Enum>();
static {
errorStyleMappings.put(DataValidation.ErrorStyle.INFO, STDataValidationErrorStyle.INFORMATION);
errorStyleMappings.put(DataValidation.ErrorStyle.STOP, STDataValidationErrorStyle.STOP);
errorStyleMappings.put(DataValidation.ErrorStyle.WARNING, STDataValidationErrorStyle.WARNING);
}
static {
operatorTypeMappings.put(DataValidationConstraint.OperatorType.BETWEEN,STDataValidationOperator.BETWEEN);
operatorTypeMappings.put(DataValidationConstraint.OperatorType.NOT_BETWEEN,STDataValidationOperator.NOT_BETWEEN);
operatorTypeMappings.put(DataValidationConstraint.OperatorType.EQUAL,STDataValidationOperator.EQUAL);
operatorTypeMappings.put(DataValidationConstraint.OperatorType.NOT_EQUAL,STDataValidationOperator.NOT_EQUAL);
operatorTypeMappings.put(DataValidationConstraint.OperatorType.GREATER_THAN,STDataValidationOperator.GREATER_THAN);
operatorTypeMappings.put(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL,STDataValidationOperator.GREATER_THAN_OR_EQUAL);
operatorTypeMappings.put(DataValidationConstraint.OperatorType.LESS_THAN,STDataValidationOperator.LESS_THAN);
operatorTypeMappings.put(DataValidationConstraint.OperatorType.LESS_OR_EQUAL,STDataValidationOperator.LESS_THAN_OR_EQUAL);
for( Map.Entry<Integer,STDataValidationOperator.Enum> entry : operatorTypeMappings.entrySet() ) {
operatorTypeReverseMappings.put(entry.getValue(),entry.getKey());
}
}

static {
validationTypeMappings.put(DataValidationConstraint.ValidationType.FORMULA,STDataValidationType.CUSTOM);
validationTypeMappings.put(DataValidationConstraint.ValidationType.DATE,STDataValidationType.DATE);
validationTypeMappings.put(DataValidationConstraint.ValidationType.DECIMAL,STDataValidationType.DECIMAL);
validationTypeMappings.put(DataValidationConstraint.ValidationType.LIST,STDataValidationType.LIST);
validationTypeMappings.put(DataValidationConstraint.ValidationType.ANY,STDataValidationType.NONE);
validationTypeMappings.put(DataValidationConstraint.ValidationType.TEXT_LENGTH,STDataValidationType.TEXT_LENGTH);
validationTypeMappings.put(DataValidationConstraint.ValidationType.TIME,STDataValidationType.TIME);
validationTypeMappings.put(DataValidationConstraint.ValidationType.INTEGER,STDataValidationType.WHOLE);
for( Map.Entry<Integer,STDataValidationType.Enum> entry : validationTypeMappings.entrySet() ) {
validationTypeReverseMappings.put(entry.getValue(),entry.getKey());
}
}

XSSFDataValidation(CellRangeAddressList regions,CTDataValidation ctDataValidation) {
super();
this.validationConstraint = getConstraint(ctDataValidation);
this.ctDdataValidation = ctDataValidation;
this.regions = regions;
this.ctDdataValidation.setErrorStyle(STDataValidationErrorStyle.STOP);
this.ctDdataValidation.setAllowBlank(true);
}

public XSSFDataValidation(XSSFDataValidationConstraint constraint,CellRangeAddressList regions,CTDataValidation ctDataValidation) {
super();
this.validationConstraint = constraint;
this.ctDdataValidation = ctDataValidation;
this.regions = regions;
this.ctDdataValidation.setErrorStyle(STDataValidationErrorStyle.STOP);
this.ctDdataValidation.setAllowBlank(true);
}
CTDataValidation getCtDdataValidation() {
return ctDdataValidation;
}



/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#createErrorBox(java.lang.String, java.lang.String)
*/
public void createErrorBox(String title, String text) {
ctDdataValidation.setErrorTitle(title);
ctDdataValidation.setError(text);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#createPromptBox(java.lang.String, java.lang.String)
*/
public void createPromptBox(String title, String text) {
ctDdataValidation.setPromptTitle(title);
ctDdataValidation.setPrompt(text);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getEmptyCellAllowed()
*/
public boolean getEmptyCellAllowed() {
return ctDdataValidation.getAllowBlank();
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getErrorBoxText()
*/
public String getErrorBoxText() {
return ctDdataValidation.getError();
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getErrorBoxTitle()
*/
public String getErrorBoxTitle() {
return ctDdataValidation.getErrorTitle();
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getErrorStyle()
*/
public int getErrorStyle() {
return ctDdataValidation.getErrorStyle().intValue();
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getPromptBoxText()
*/
public String getPromptBoxText() {
return ctDdataValidation.getPrompt();
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getPromptBoxTitle()
*/
public String getPromptBoxTitle() {
return ctDdataValidation.getPromptTitle();
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getShowErrorBox()
*/
public boolean getShowErrorBox() {
return ctDdataValidation.getShowErrorMessage();
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getShowPromptBox()
*/
public boolean getShowPromptBox() {
return ctDdataValidation.getShowInputMessage();
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getSuppressDropDownArrow()
*/
public boolean getSuppressDropDownArrow() {
return !ctDdataValidation.getShowDropDown();
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#getValidationConstraint()
*/
public DataValidationConstraint getValidationConstraint() {
return validationConstraint;
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#setEmptyCellAllowed(boolean)
*/
public void setEmptyCellAllowed(boolean allowed) {
ctDdataValidation.setAllowBlank(allowed);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#setErrorStyle(int)
*/
public void setErrorStyle(int errorStyle) {
ctDdataValidation.setErrorStyle(errorStyleMappings.get(errorStyle));
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#setShowErrorBox(boolean)
*/
public void setShowErrorBox(boolean show) {
ctDdataValidation.setShowErrorMessage(show);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#setShowPromptBox(boolean)
*/
public void setShowPromptBox(boolean show) {
ctDdataValidation.setShowInputMessage(show);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidation#setSuppressDropDownArrow(boolean)
*/
public void setSuppressDropDownArrow(boolean suppress) {
if (validationConstraint.getValidationType()==ValidationType.LIST) {
ctDdataValidation.setShowDropDown(!suppress);
}
}

public CellRangeAddressList getRegions() {
return regions;
}
public String prettyPrint() {
StringBuilder builder = new StringBuilder();
for(CellRangeAddress address : regions.getCellRangeAddresses()) {
builder.append(address.formatAsString());
}
builder.append(" => ");
builder.append(this.validationConstraint.prettyPrint());
return builder.toString();
}
private XSSFDataValidationConstraint getConstraint(CTDataValidation ctDataValidation) {
XSSFDataValidationConstraint constraint = null;
String formula1 = ctDataValidation.getFormula1();
String formula2 = ctDataValidation.getFormula2();
Enum operator = ctDataValidation.getOperator();
org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationType.Enum type = ctDataValidation.getType();
Integer validationType = XSSFDataValidation.validationTypeReverseMappings.get(type);
Integer operatorType = XSSFDataValidation.operatorTypeReverseMappings.get(operator);
constraint = new XSSFDataValidationConstraint(validationType,operatorType, formula1,formula2);
return constraint;
}
}

+ 194
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidationConstraint.java View File

@@ -0,0 +1,194 @@
/**
*
*/
package org.apache.poi.xssf.usermodel;

import java.util.Arrays;

import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationType;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationOperator.Enum;

/**
* @author <a href="rjankiraman@emptoris.com">Radhakrishnan J</a>
*
*/
public class XSSFDataValidationConstraint implements DataValidationConstraint {
private String formula1;
private String formula2;
private int validationType = -1;
private int operator = -1;
private String[] explicitListOfValues;

public XSSFDataValidationConstraint(String[] explicitListOfValues) {
if( explicitListOfValues==null || explicitListOfValues.length==0) {
throw new IllegalArgumentException("List validation with explicit values must specify at least one value");
}
this.validationType = ValidationType.LIST;
setExplicitListValues(explicitListOfValues);
validate();
}
public XSSFDataValidationConstraint(int validationType,String formula1) {
super();
setFormula1(formula1);
this.validationType = validationType;
validate();
}



public XSSFDataValidationConstraint(int validationType, int operator,String formula1) {
super();
setFormula1(formula1);
this.validationType = validationType;
this.operator = operator;
validate();
}

public XSSFDataValidationConstraint(int validationType, int operator,String formula1, String formula2) {
super();
setFormula1(formula1);
setFormula2(formula2);
this.validationType = validationType;
this.operator = operator;
validate();
//FIXME: Need to confirm if this is not a formula.
if( ValidationType.LIST==validationType) {
explicitListOfValues = formula1.split(",");
}
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getExplicitListValues()
*/
public String[] getExplicitListValues() {
return explicitListOfValues;
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getFormula1()
*/
public String getFormula1() {
return formula1;
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getFormula2()
*/
public String getFormula2() {
return formula2;
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getOperator()
*/
public int getOperator() {
return operator;
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getValidationType()
*/
public int getValidationType() {
return validationType;
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setExplicitListValues(java.lang.String[])
*/
public void setExplicitListValues(String[] explicitListValues) {
this.explicitListOfValues = explicitListValues;
if( explicitListOfValues!=null && explicitListOfValues.length > 0 ) {
StringBuilder builder = new StringBuilder("\"");
for (int i = 0; i < explicitListValues.length; i++) {
String string = explicitListValues[i];
if( builder.length() > 1) {
builder.append(",");
}
builder.append(string);
}
builder.append("\"");
setFormula1(builder.toString());
}
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setFormula1(java.lang.String)
*/
public void setFormula1(String formula1) {
this.formula1 = removeLeadingEquals(formula1);
}

protected String removeLeadingEquals(String formula1) {
return isFormulaEmpty(formula1) ? formula1 : formula1.charAt(0)=='=' ? formula1.substring(1) : formula1;
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setFormula2(java.lang.String)
*/
public void setFormula2(String formula2) {
this.formula2 = removeLeadingEquals(formula2);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setOperator(int)
*/
public void setOperator(int operator) {
this.operator = operator;
}

public void validate() {
if (validationType==ValidationType.ANY) {
return;
}
if (validationType==ValidationType.LIST ) {
if (isFormulaEmpty(formula1)) {
throw new IllegalArgumentException("A valid formula or a list of values must be specified for list validation.");
}
} else {
if( isFormulaEmpty(formula1) ) {
throw new IllegalArgumentException("Formula is not specified. Formula is required for all validation types except explicit list validation.");
}
if( validationType!= ValidationType.FORMULA ) {
if (operator==-1) {
throw new IllegalArgumentException("This validation type requires an operator to be specified.");
} else if (( operator==OperatorType.BETWEEN || operator==OperatorType.NOT_BETWEEN) && isFormulaEmpty(formula2)) {
throw new IllegalArgumentException("Between and not between comparisons require two formulae to be specified.");
}
}
}
}

protected boolean isFormulaEmpty(String formula1) {
return formula1 == null || formula1.trim().length()==0;
}
public String prettyPrint() {
StringBuilder builder = new StringBuilder();
STDataValidationType.Enum vt = XSSFDataValidation.validationTypeMappings.get(validationType);
Enum ot = XSSFDataValidation.operatorTypeMappings.get(operator);
builder.append(vt);
builder.append(' ');
if (validationType!=ValidationType.ANY) {
if (validationType != ValidationType.LIST && validationType != ValidationType.ANY && validationType != ValidationType.FORMULA) {
builder.append(",").append(ot).append(", ");
}
final String QUOTE = "";
if (validationType == ValidationType.LIST && explicitListOfValues != null) {
builder.append(QUOTE).append(Arrays.asList(explicitListOfValues)).append(QUOTE).append(' ');
} else {
builder.append(QUOTE).append(formula1).append(QUOTE).append(' ');
}
if (formula2 != null) {
builder.append(QUOTE).append(formula2).append(QUOTE).append(' ');
}
}
return builder.toString();
}
}

+ 155
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidationHelper.java View File

@@ -0,0 +1,155 @@
/**
*
*/
package org.apache.poi.xssf.usermodel;

import java.util.ArrayList;
import java.util.List;

import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidation;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationType;

/**
* @author <a href="rjankiraman@emptoris.com">Radhakrishnan J</a>
*
*/
public class XSSFDataValidationHelper implements DataValidationHelper {
private XSSFSheet xssfSheet;
public XSSFDataValidationHelper(XSSFSheet xssfSheet) {
super();
this.xssfSheet = xssfSheet;
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createDateConstraint(int, java.lang.String, java.lang.String, java.lang.String)
*/
public DataValidationConstraint createDateConstraint(int operatorType, String formula1, String formula2, String dateFormat) {
return new XSSFDataValidationConstraint(ValidationType.DATE, operatorType,formula1, formula2);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createDecimalConstraint(int, java.lang.String, java.lang.String)
*/
public DataValidationConstraint createDecimalConstraint(int operatorType, String formula1, String formula2) {
return new XSSFDataValidationConstraint(ValidationType.DECIMAL, operatorType,formula1, formula2);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createExplicitListConstraint(java.lang.String[])
*/
public DataValidationConstraint createExplicitListConstraint(String[] listOfValues) {
return new XSSFDataValidationConstraint(listOfValues);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createFormulaListConstraint(java.lang.String)
*/
public DataValidationConstraint createFormulaListConstraint(String listFormula) {
return new XSSFDataValidationConstraint(ValidationType.LIST, listFormula);
}

public DataValidationConstraint createNumericConstraint(int validationType, int operatorType, String formula1, String formula2) {
if( validationType==ValidationType.INTEGER) {
return createIntegerConstraint(operatorType, formula1, formula2);
} else if ( validationType==ValidationType.DECIMAL) {
return createDecimalConstraint(operatorType, formula1, formula2);
} else if ( validationType==ValidationType.TEXT_LENGTH) {
return createTextLengthConstraint(operatorType, formula1, formula2);
}
return null;
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createIntegerConstraint(int, java.lang.String, java.lang.String)
*/
public DataValidationConstraint createIntegerConstraint(int operatorType, String formula1, String formula2) {
return new XSSFDataValidationConstraint(ValidationType.INTEGER, operatorType,formula1,formula2);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createTextLengthConstraint(int, java.lang.String, java.lang.String)
*/
public DataValidationConstraint createTextLengthConstraint(int operatorType, String formula1, String formula2) {
return new XSSFDataValidationConstraint(ValidationType.TEXT_LENGTH, operatorType,formula1,formula2);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createTimeConstraint(int, java.lang.String, java.lang.String, java.lang.String)
*/
public DataValidationConstraint createTimeConstraint(int operatorType, String formula1, String formula2) {
return new XSSFDataValidationConstraint(ValidationType.TIME, operatorType,formula1,formula2);
}

public DataValidationConstraint createCustomConstraint(String formula) {
return new XSSFDataValidationConstraint(ValidationType.FORMULA, formula);
}

/* (non-Javadoc)
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createValidation(org.apache.poi.ss.usermodel.DataValidationConstraint, org.apache.poi.ss.util.CellRangeAddressList)
*/
public DataValidation createValidation(DataValidationConstraint constraint, CellRangeAddressList cellRangeAddressList) {
XSSFDataValidationConstraint dataValidationConstraint = (XSSFDataValidationConstraint)constraint;
CTDataValidation newDataValidation = CTDataValidation.Factory.newInstance();

int validationType = constraint.getValidationType();
switch(validationType) {
case DataValidationConstraint.ValidationType.LIST:
newDataValidation.setType(STDataValidationType.LIST);
newDataValidation.setFormula1(constraint.getFormula1());
break;
case DataValidationConstraint.ValidationType.ANY:
newDataValidation.setType(STDataValidationType.NONE);
break;
case DataValidationConstraint.ValidationType.TEXT_LENGTH:
newDataValidation.setType(STDataValidationType.TEXT_LENGTH);
break;
case DataValidationConstraint.ValidationType.DATE:
newDataValidation.setType(STDataValidationType.DATE);
break;
case DataValidationConstraint.ValidationType.INTEGER:
newDataValidation.setType(STDataValidationType.WHOLE);
break;
case DataValidationConstraint.ValidationType.DECIMAL:
newDataValidation.setType(STDataValidationType.DECIMAL);
break;
case DataValidationConstraint.ValidationType.TIME:
newDataValidation.setType(STDataValidationType.TIME);
break;
case DataValidationConstraint.ValidationType.FORMULA:
newDataValidation.setType(STDataValidationType.CUSTOM);
break;
default:
newDataValidation.setType(STDataValidationType.NONE);
}
if (validationType!=ValidationType.ANY && validationType!=ValidationType.LIST) {
newDataValidation.setOperator(XSSFDataValidation.operatorTypeMappings.get(constraint.getOperator()));
if (constraint.getFormula1() != null) {
newDataValidation.setFormula1(constraint.getFormula1());
}
if (constraint.getFormula2() != null) {
newDataValidation.setFormula2(constraint.getFormula2());
}
}
CellRangeAddress[] cellRangeAddresses = cellRangeAddressList.getCellRangeAddresses();
List<String> sqref = new ArrayList<String>();
for (int i = 0; i < cellRangeAddresses.length; i++) {
CellRangeAddress cellRangeAddress = cellRangeAddresses[i];
sqref.add(cellRangeAddress.formatAsString());
}
newDataValidation.setSqref(sqref);
return new XSSFDataValidation(dataValidationConstraint,cellRangeAddressList,newDataValidation);
}
}

+ 86
- 1
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java View File

@@ -42,11 +42,14 @@ import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellRange;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Footer;
import org.apache.poi.ss.usermodel.Header;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.SSCellRange;
import org.apache.poi.util.Internal;
@@ -58,7 +61,41 @@ import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBreak;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidation;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidations;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDrawing;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTLegacyDrawing;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCells;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOutlinePr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageBreak;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageMargins;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageSetUpPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPane;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPrintOptions;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSelection;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetFormatPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetProtection;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetView;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetViews;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPaneState;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;

/**
* High level representation of a SpreadsheetML worksheet.
@@ -82,6 +119,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
private CommentsTable sheetComments;
private Map<Integer, XSSFCell> sharedFormulas;
private List<CellRangeAddress> arrayFormulas;
private XSSFDataValidationHelper dataValidationHelper;

/**
* Creates new XSSFSheet - called by XSSFWorkbook to create a sheet from scratch.
@@ -90,6 +128,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
*/
protected XSSFSheet() {
super();
dataValidationHelper = new XSSFDataValidationHelper(this);
onDocumentCreate();
}

@@ -102,6 +141,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
*/
protected XSSFSheet(PackagePart part, PackageRelationship rel) {
super(part, rel);
dataValidationHelper = new XSSFDataValidationHelper(this);
}

/**
@@ -2794,4 +2834,49 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
String ref = ((XSSFCell)cell).getCTCell().getR();
throw new IllegalArgumentException("Cell " + ref + " is not part of an array formula.");
}


public DataValidationHelper getDataValidationHelper() {
return dataValidationHelper;
}
public List<XSSFDataValidation> getDataValidations() {
List<XSSFDataValidation> xssfValidations = new ArrayList<XSSFDataValidation>();
CTDataValidations dataValidations = this.worksheet.getDataValidations();
if( dataValidations!=null && dataValidations.getCount() > 0 ) {
CTDataValidation[] dataValidationList = dataValidations.getDataValidationArray();
for (CTDataValidation ctDataValidation : dataValidationList) {
CellRangeAddressList addressList = new CellRangeAddressList();
@SuppressWarnings("unchecked")
List<String> sqref = ctDataValidation.getSqref();
for (String stRef : sqref) {
String[] regions = stRef.split(" ");
for (int i = 0; i < regions.length; i++) {
String[] parts = regions[i].split(":");
CellReference begin = new CellReference(parts[0]);
CellReference end = parts.length > 1 ? new CellReference(parts[1]) : begin;
CellRangeAddress cellRangeAddress = new CellRangeAddress(begin.getRow(), end.getRow(), begin.getCol(), end.getCol());
addressList.addCellRangeAddress(cellRangeAddress);
}
}
XSSFDataValidation xssfDataValidation = new XSSFDataValidation(addressList, ctDataValidation);
xssfValidations.add(xssfDataValidation);
}
}
return xssfValidations;
}

public void addValidationData(DataValidation dataValidation) {
XSSFDataValidation xssfDataValidation = (XSSFDataValidation)dataValidation;
CTDataValidations dataValidations = worksheet.getDataValidations();
if( dataValidations==null ) {
dataValidations = worksheet.addNewDataValidations();
}
int currentCount = dataValidations.getDataValidationArray().length;
CTDataValidation newval = dataValidations.addNewDataValidation();
newval.set(xssfDataValidation.getCtDdataValidation());
dataValidations.setCount(currentCount + 1);

}
}

+ 242
- 0
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDataValidation.java View File

@@ -0,0 +1,242 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.xssf.usermodel;

import java.math.BigDecimal;
import java.util.List;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.DataValidationConstraint.OperatorType;
import org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples;

public class TestXSSFDataValidation extends BaseTestDataValidation {

public TestXSSFDataValidation(){
super(XSSFITestDataProvider.instance);
}

public void testAddValidations() throws Exception {
XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("DataValidations-49244.xlsx");
Sheet sheet = workbook.getSheetAt(0);
List<XSSFDataValidation> dataValidations = ((XSSFSheet)sheet).getDataValidations();
/**
* For each validation type, there are two cells with the same validation. This tests
* application of a single validation definition to multiple cells.
*
* For list ( 3 validations for explicit and 3 for formula )
* - one validation that allows blank.
* - one that does not allow blank.
* - one that does not show the drop down arrow.
* = 2
*
* For number validations ( integer/decimal and text length ) with 8 different types of operators.
* = 50
*
* = 52 ( Total )
*/
assertEquals(52,dataValidations.size());

DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
int[] validationTypes = new int[]{ValidationType.INTEGER,ValidationType.DECIMAL,ValidationType.TEXT_LENGTH};
int[] singleOperandOperatorTypes = new int[]{
OperatorType.LESS_THAN,OperatorType.LESS_OR_EQUAL,
OperatorType.GREATER_THAN,OperatorType.GREATER_OR_EQUAL,
OperatorType.EQUAL,OperatorType.NOT_EQUAL
} ;
int[] doubleOperandOperatorTypes = new int[]{
OperatorType.BETWEEN,OperatorType.NOT_BETWEEN
};
BigDecimal value = new BigDecimal("10"),value2 = new BigDecimal("20");
BigDecimal dvalue = new BigDecimal("10.001"),dvalue2 = new BigDecimal("19.999");
final int lastRow = sheet.getLastRowNum();
int offset = lastRow + 3;
int lastKnownNumValidations = dataValidations.size();
Row row = sheet.createRow(offset++);
Cell cell = row.createCell(0);
DataValidationConstraint explicitListValidation = dataValidationHelper.createExplicitListConstraint(new String[]{"MA","MI","CA"});
CellRangeAddressList cellRangeAddressList = new CellRangeAddressList();
cellRangeAddressList.addCellRangeAddress(cell.getRowIndex(), cell.getColumnIndex(), cell.getRowIndex(), cell.getColumnIndex());
DataValidation dataValidation = dataValidationHelper.createValidation(explicitListValidation, cellRangeAddressList);
setOtherValidationParameters(dataValidation);
sheet.addValidationData(dataValidation);
lastKnownNumValidations++;
row = sheet.createRow(offset++);
cell = row.createCell(0);

cellRangeAddressList = new CellRangeAddressList();
cellRangeAddressList.addCellRangeAddress(cell.getRowIndex(), cell.getColumnIndex(), cell.getRowIndex(), cell.getColumnIndex());
Cell firstCell = row.createCell(1);firstCell.setCellValue("UT");
Cell secondCell = row.createCell(2);secondCell.setCellValue("MN");
Cell thirdCell = row.createCell(3);thirdCell.setCellValue("IL");
int rowNum = row.getRowNum() + 1;
String listFormula = new StringBuilder("$B$").append(rowNum).append(":").append("$D$").append(rowNum).toString();
DataValidationConstraint formulaListValidation = dataValidationHelper.createFormulaListConstraint(listFormula);
dataValidation = dataValidationHelper.createValidation(formulaListValidation, cellRangeAddressList);
setOtherValidationParameters(dataValidation);
sheet.addValidationData(dataValidation);
lastKnownNumValidations++;
offset++;
offset++;
for (int i = 0; i < validationTypes.length; i++) {
int validationType = validationTypes[i];
offset = offset + 2;
final Row row0 = sheet.createRow(offset++);
Cell cell_10 = row0.createCell(0);
cell_10.setCellValue(validationType==ValidationType.DECIMAL ? "Decimal " : validationType==ValidationType.INTEGER ? "Integer" : "Text Length");
offset++;
for (int j = 0; j < singleOperandOperatorTypes.length; j++) {
int operatorType = singleOperandOperatorTypes[j];
final Row row1 = sheet.createRow(offset++);
//For Integer (> and >=) we add 1 extra cell for validations whose formulae reference other cells.
final Row row2 = i==0 && j < 2 ? sheet.createRow(offset++) : null;
cell_10 = row1.createCell(0);
cell_10.setCellValue(XSSFDataValidation.operatorTypeMappings.get(operatorType).toString());
Cell cell_11 = row1.createCell(1);
Cell cell_21 = row1.createCell(2);
Cell cell_22 = i==0 && j < 2 ? row2.createCell(2) : null;
Cell cell_13 = row1.createCell(3);
cell_13.setCellType(Cell.CELL_TYPE_NUMERIC);
cell_13.setCellValue(validationType==ValidationType.DECIMAL ? dvalue.doubleValue() : value.intValue());

//First create value based validation;
DataValidationConstraint constraint = dataValidationHelper.createNumericConstraint(validationType,operatorType, value.toString(), null);
cellRangeAddressList = new CellRangeAddressList();
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_11.getRowIndex(),cell_11.getRowIndex(),cell_11.getColumnIndex(),cell_11.getColumnIndex()));
DataValidation validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList);
setOtherValidationParameters(validation);
sheet.addValidationData(validation);
assertEquals(++lastKnownNumValidations,((XSSFSheet)sheet).getDataValidations().size());
//Now create real formula based validation.
String formula1 = new CellReference(cell_13.getRowIndex(),cell_13.getColumnIndex()).formatAsString();
constraint = dataValidationHelper.createNumericConstraint(validationType,operatorType, formula1, null);
if (i==0 && j==0) {
cellRangeAddressList = new CellRangeAddressList();
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_21.getRowIndex(), cell_21.getRowIndex(), cell_21.getColumnIndex(), cell_21.getColumnIndex()));
validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList);
setOtherValidationParameters(validation);
sheet.addValidationData(validation);
assertEquals(++lastKnownNumValidations, ((XSSFSheet) sheet).getDataValidations().size());
cellRangeAddressList = new CellRangeAddressList();
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex()));
validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList);
setOtherValidationParameters( validation);
sheet.addValidationData(validation);
assertEquals(++lastKnownNumValidations, ((XSSFSheet) sheet).getDataValidations().size());
} else if(i==0 && j==1 ){
cellRangeAddressList = new CellRangeAddressList();
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_21.getRowIndex(), cell_21.getRowIndex(), cell_21.getColumnIndex(), cell_21.getColumnIndex()));
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex()));
validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList);
setOtherValidationParameters( validation);
sheet.addValidationData(validation);
assertEquals(++lastKnownNumValidations, ((XSSFSheet) sheet).getDataValidations().size());
} else {
cellRangeAddressList = new CellRangeAddressList();
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_21.getRowIndex(), cell_21.getRowIndex(), cell_21.getColumnIndex(), cell_21.getColumnIndex()));
validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList);
setOtherValidationParameters(validation);
sheet.addValidationData(validation);
assertEquals(++lastKnownNumValidations, ((XSSFSheet) sheet).getDataValidations().size());
}
}

for (int j = 0; j < doubleOperandOperatorTypes.length; j++) {
int operatorType = doubleOperandOperatorTypes[j];
final Row row1 = sheet.createRow(offset++);
cell_10 = row1.createCell(0);
cell_10.setCellValue(XSSFDataValidation.operatorTypeMappings.get(operatorType).toString());
Cell cell_11 = row1.createCell(1);
Cell cell_21 = row1.createCell(2);
Cell cell_13 = row1.createCell(3);
Cell cell_14 = row1.createCell(4);
String value1String = validationType==ValidationType.DECIMAL ? dvalue.toString() : value.toString();
cell_13.setCellType(Cell.CELL_TYPE_NUMERIC);
cell_13.setCellValue(validationType==ValidationType.DECIMAL ? dvalue.doubleValue() : value.intValue());

String value2String = validationType==ValidationType.DECIMAL ? dvalue2.toString() : value2.toString();
cell_14.setCellType(Cell.CELL_TYPE_NUMERIC);
cell_14.setCellValue(validationType==ValidationType.DECIMAL ? dvalue2.doubleValue() : value2.intValue());
//First create value based validation;
DataValidationConstraint constraint = dataValidationHelper.createNumericConstraint(validationType,operatorType, value1String, value2String);
cellRangeAddressList = new CellRangeAddressList();
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_11.getRowIndex(),cell_11.getRowIndex(),cell_11.getColumnIndex(),cell_11.getColumnIndex()));
DataValidation validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList);
setOtherValidationParameters(validation);
sheet.addValidationData(validation);
assertEquals(++lastKnownNumValidations,((XSSFSheet)sheet).getDataValidations().size());
//Now create real formula based validation.
String formula1 = new CellReference(cell_13.getRowIndex(),cell_13.getColumnIndex()).formatAsString();
String formula2 = new CellReference(cell_14.getRowIndex(),cell_14.getColumnIndex()).formatAsString();
constraint = dataValidationHelper.createNumericConstraint(validationType,operatorType, formula1, formula2);
cellRangeAddressList = new CellRangeAddressList();
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_21.getRowIndex(),cell_21.getRowIndex(),cell_21.getColumnIndex(),cell_21.getColumnIndex()));
validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList);
setOtherValidationParameters(validation);
sheet.addValidationData(validation);
assertEquals(++lastKnownNumValidations,((XSSFSheet)sheet).getDataValidations().size());
}
}

workbook = XSSFTestDataSamples.writeOutAndReadBack(workbook);
Sheet sheetAt = workbook.getSheetAt(0);
assertEquals(lastKnownNumValidations,((XSSFSheet)sheetAt).getDataValidations().size());
}

protected void setOtherValidationParameters(DataValidation validation) {
boolean yesNo = true;
validation.setEmptyCellAllowed(yesNo);
validation.setShowErrorBox(yesNo);
validation.setShowPromptBox(yesNo);
validation.createErrorBox("Error Message Title", "Error Message");
validation.createPromptBox("Prompt", "Enter some value");
validation.setSuppressDropDownArrow(yesNo);
}
}

+ 11
- 442
src/testcases/org/apache/poi/hssf/usermodel/TestDataValidation.java View File

@@ -28,6 +28,7 @@ import java.io.PrintStream;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.eventmodel.ERFListener;
import org.apache.poi.hssf.eventmodel.EventRecordFactory;
@@ -35,6 +36,7 @@ import org.apache.poi.hssf.record.DVRecord;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;

@@ -43,448 +45,14 @@ import org.apache.poi.ss.util.CellRangeAddressList;
*
* @author Dragos Buleandra ( dragos.buleandra@trade2b.ro )
*/
public final class TestDataValidation extends TestCase {
public final class TestDataValidation extends BaseTestDataValidation {

/** Convenient access to ERROR_STYLE constants */
/*package*/ static final HSSFDataValidation.ErrorStyle ES = null;
/** Convenient access to OPERATOR constants */
/*package*/ static final DVConstraint.ValidationType VT = null;
/** Convenient access to OPERATOR constants */
/*package*/ static final DVConstraint.OperatorType OP = null;
public TestDataValidation(){
super(HSSFITestDataProvider.instance);
}

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(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.createCustomFormulaConstraint(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(1);
cell.setCellStyle(style_1);
setCellValue(cell, strCondition);
// allow empty cells
cell = row.createCell(2);
cell.setCellStyle(style_2);
setCellValue(cell, ((allowEmpty) ? "yes" : "no"));
// show input box
cell = row.createCell(3);
cell.setCellStyle(style_2);
setCellValue(cell, ((inputBox) ? "yes" : "no"));
// show error box
cell = row.createCell(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(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 CellRangeAddress(sheet.getPhysicalNumberOfRows()-1, sheet.getPhysicalNumberOfRows()-1, 0, 5));
HSSFCell cell = row.createCell(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(i).setCellStyle(_style_4);
if (i == 2 || i == 3 || i == 4) {
sheet.setColumnWidth(i, 3500);
} else if (i == 5) {
sheet.setColumnWidth(i, 10000);
} else {
sheet.setColumnWidth(i, 8000);
}
}
HSSFCell cell = row.getCell(0);
setCellValue(cell, "Data validation cells");
cell = row.getCell(1);
setCellValue(cell, "Condition");
cell = row.getCell(2);
setCellValue(cell, "Allow blank");
cell = row.getCell(3);
setCellValue(cell, "Prompt box");
cell = row.getCell(4);
setCellValue(cell, "Error box");
cell = row.getCell(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 CellRangeAddress(sheet.getPhysicalNumberOfRows()-1, sheet.getPhysicalNumberOfRows()-1, 0, 5));
HSSFCell cell = row.createCell(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.setRefersToFormula(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(0), cellStrValue);
}
// add list data on another sheet
for (int i = 0; i < 10; i++) {
HSSFRow currRow = dataSheet.createRow(i + 0);
setCellValue(currRow.createCell(0), "Data a" + i);
setCellValue(currRow.createCell(1), "Data b" + i);
setCellValue(currRow.createCell(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 !");
public void assertDataValidation(Workbook wb) {

ByteArrayOutputStream baos = new ByteArrayOutputStream(22000);
try {
@@ -572,9 +140,10 @@ public final class TestDataValidation extends TestCase {
// and then deleting the row that contains the cell.
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("dvEmpty.xls");
int dvRow = 0;
HSSFSheet sheet = wb.getSheetAt(0);
DVConstraint dc = DVConstraint.createNumericConstraint(VT.INTEGER, OP.EQUAL, "42", null);
HSSFDataValidation dv = new HSSFDataValidation(new CellRangeAddressList(dvRow, dvRow, 0, 0), dc);
Sheet sheet = wb.getSheetAt(0);
DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
DataValidationConstraint dc = dataValidationHelper.createIntegerConstraint(OP.EQUAL, "42", null);
DataValidation dv = dataValidationHelper.createValidation(dc,new CellRangeAddressList(dvRow, dvRow, 0, 0));
dv.setEmptyCellAllowed(false);
dv.setErrorStyle(ES.STOP);

+ 7
- 4
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java View File

@@ -42,6 +42,9 @@ import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.record.aggregates.WorksheetProtectionBlock;
import org.apache.poi.hssf.usermodel.RecordInspector.RecordCollector;
import org.apache.poi.ss.usermodel.BaseTestSheet;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.TempFile;
@@ -382,10 +385,10 @@ public final class TestHSSFSheet extends BaseTestSheet {
HSSFSheet sheet = workbook.createSheet("Sheet1");
sheet.protectSheet("secret");

DVConstraint dvc = DVConstraint.createNumericConstraint(DVConstraint.ValidationType.INTEGER,
DVConstraint.OperatorType.BETWEEN, "10", "100");
DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
DataValidationConstraint dvc = dataValidationHelper.createIntegerConstraint(DataValidationConstraint.OperatorType.BETWEEN, "10", "100");
CellRangeAddressList numericCellAddressList = new CellRangeAddressList(0, 0, 1, 1);
HSSFDataValidation dv = new HSSFDataValidation(numericCellAddressList, dvc);
DataValidation dv = dataValidationHelper.createValidation(dvc,numericCellAddressList);
try {
sheet.addValidationData(dv);
} catch (IllegalStateException e) {
@@ -535,7 +538,7 @@ public final class TestHSSFSheet extends BaseTestSheet {
int minWithRow1And2 = 6400;
int maxWithRow1And2 = 7800;
int minWithRow1Only = 2750;
int maxWithRow1Only = 3300;
int maxWithRow1Only = 3400;

// autoSize the first column and check its size before the merged region (1,0,1,1) is set:
// it has to be based on the 2nd row width

+ 501
- 0
src/testcases/org/apache/poi/ss/usermodel/BaseTestDataValidation.java View File

@@ -0,0 +1,501 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.ss.usermodel;

import junit.framework.TestCase;

import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

/**
* Class for testing Excel's data validation mechanism
*
* @author Dragos Buleandra ( dragos.buleandra@trade2b.ro )
*/
public abstract class BaseTestDataValidation extends TestCase {
private final ITestDataProvider _testDataProvider;

private static final POILogger log = POILogFactory.getLogger(BaseTestDataValidation.class);

protected BaseTestDataValidation(ITestDataProvider testDataProvider) {
_testDataProvider = testDataProvider;
}

/** Convenient access to ERROR_STYLE constants */
protected static final DataValidation.ErrorStyle ES = null;
/** Convenient access to OPERATOR constants */
protected static final DataValidationConstraint.ValidationType VT = null;
/** Convenient access to OPERATOR constants */
protected static final DataValidationConstraint.OperatorType OP = null;

private static final class ValidationAdder {

private final CellStyle _style_1;
private final CellStyle _style_2;
private final int _validationType;
private final Sheet _sheet;
private int _currentRowIndex;
private final CellStyle _cellStyle;

public ValidationAdder(Sheet fSheet, CellStyle style_1, CellStyle style_2,
CellStyle 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++;

DataValidationHelper dataValidationHelper = _sheet.getDataValidationHelper();
DataValidationConstraint dc = createConstraint(dataValidationHelper,operatorType, firstFormula, secondFormula, explicitListValues);

DataValidation dv = dataValidationHelper.createValidation(dc,new CellRangeAddressList(rowNum, rowNum, 0, 0));

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) {
Row row = _sheet.getRow(_sheet.getPhysicalNumberOfRows() - 1);
Cell cell = row.createCell(0);
cell.setCellStyle(_cellStyle);
}
writeOtherSettings(_sheet, _style_1, promptDescr);
}
private DataValidationConstraint createConstraint(DataValidationHelper dataValidationHelper,int operatorType, String firstFormula,
String secondFormula, String[] explicitListValues) {
if (_validationType == VT.LIST) {
if (explicitListValues != null) {
return dataValidationHelper.createExplicitListConstraint(explicitListValues);
}
return dataValidationHelper.createFormulaListConstraint(firstFormula);
}
if (_validationType == VT.TIME) {
return dataValidationHelper.createTimeConstraint(operatorType, firstFormula, secondFormula);
}
if (_validationType == VT.DATE) {
return dataValidationHelper.createDateConstraint(operatorType, firstFormula, secondFormula, null);
}
if (_validationType == VT.FORMULA) {
return dataValidationHelper.createCustomConstraint(firstFormula);
}

if( _validationType == VT.INTEGER) {
return dataValidationHelper.createIntegerConstraint(operatorType, firstFormula, secondFormula);
}
if( _validationType == VT.DECIMAL) {
return dataValidationHelper.createDecimalConstraint(operatorType, firstFormula, secondFormula);
}
if( _validationType == VT.TEXT_LENGTH) {
return dataValidationHelper.createTextLengthConstraint(operatorType, firstFormula, secondFormula);
}
return null;
}
/**
* writes plain text values into cells in a tabular format to form comments readable from within
* the spreadsheet.
*/
private static void writeDataValidationSettings(Sheet sheet, CellStyle style_1,
CellStyle style_2, String strCondition, boolean allowEmpty, boolean inputBox,
boolean errorBox) {
Row row = sheet.createRow(sheet.getPhysicalNumberOfRows());
// condition's string
Cell cell = row.createCell(1);
cell.setCellStyle(style_1);
setCellValue(cell, strCondition);
// allow empty cells
cell = row.createCell(2);
cell.setCellStyle(style_2);
setCellValue(cell, ((allowEmpty) ? "yes" : "no"));
// show input box
cell = row.createCell(3);
cell.setCellStyle(style_2);
setCellValue(cell, ((inputBox) ? "yes" : "no"));
// show error box
cell = row.createCell(4);
cell.setCellStyle(style_2);
setCellValue(cell, ((errorBox) ? "yes" : "no"));
}
private static void writeOtherSettings(Sheet sheet, CellStyle style,
String strStettings) {
Row row = sheet.getRow(sheet.getPhysicalNumberOfRows() - 1);
Cell cell = row.createCell(5);
cell.setCellStyle(style);
setCellValue(cell, strStettings);
}
public void addListValidation(String[] explicitListValues, String listFormula, String listValsDescr,
boolean allowEmpty, boolean suppressDropDown) {
String promptDescr = (allowEmpty ? "empty ok" : "not empty")
+ ", " + (suppressDropDown ? "no drop-down" : "drop-down");
addValidationInternal(VT.LIST, listFormula, null, ES.STOP, listValsDescr, promptDescr,
allowEmpty, false, true, suppressDropDown, explicitListValues);
}
}

private static void log(String msg) {
log.log(POILogger.INFO, msg);
}

/**
* Manages the cell styles used for formatting the output spreadsheet
*/
private static final class WorkbookFormatter {

private final Workbook _wb;
private final CellStyle _style_1;
private final CellStyle _style_2;
private final CellStyle _style_3;
private final CellStyle _style_4;
private Sheet _currentSheet;

public WorkbookFormatter(Workbook wb) {
_wb = wb;
_style_1 = createStyle( wb, CellStyle.ALIGN_LEFT );
_style_2 = createStyle( wb, CellStyle.ALIGN_CENTER );
_style_3 = createStyle( wb, CellStyle.ALIGN_CENTER, IndexedColors.GREY_25_PERCENT.getIndex(), true );
_style_4 = createHeaderStyle(wb);
}

private static CellStyle createStyle(Workbook wb, short h_align, short color,
boolean bold) {
Font font = wb.createFont();
if (bold) {
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
}

CellStyle cellStyle = wb.createCellStyle();
cellStyle.setFont(font);
cellStyle.setFillForegroundColor(color);
cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
cellStyle.setAlignment(h_align);
cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
cellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setBorderTop(CellStyle.BORDER_THIN);
cellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setBorderRight(CellStyle.BORDER_THIN);
cellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
cellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());

return cellStyle;
}

private static CellStyle createStyle(Workbook wb, short h_align) {
return createStyle(wb, h_align, IndexedColors.WHITE.getIndex(), false);
}
private static CellStyle createHeaderStyle(Workbook wb) {
Font font = wb.createFont();
font.setColor( IndexedColors.WHITE.getIndex() );
font.setBoldweight(Font.BOLDWEIGHT_BOLD);

CellStyle cellStyle = wb.createCellStyle();
cellStyle.setFillForegroundColor(IndexedColors.BLUE_GREY.getIndex());
cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
cellStyle.setLeftBorderColor(IndexedColors.WHITE.getIndex());
cellStyle.setBorderTop(CellStyle.BORDER_THIN);
cellStyle.setTopBorderColor(IndexedColors.WHITE.getIndex());
cellStyle.setBorderRight(CellStyle.BORDER_THIN);
cellStyle.setRightBorderColor(IndexedColors.WHITE.getIndex());
cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
cellStyle.setBottomBorderColor(IndexedColors.WHITE.getIndex());
cellStyle.setFont(font);
return cellStyle;
}


public Sheet createSheet(String sheetName) {
_currentSheet = _wb.createSheet(sheetName);
return _currentSheet;
}
public void createDVTypeRow(String strTypeDescription) {
Sheet sheet = _currentSheet;
Row row = sheet.createRow(sheet.getPhysicalNumberOfRows());
sheet.addMergedRegion(new CellRangeAddress(sheet.getPhysicalNumberOfRows()-1, sheet.getPhysicalNumberOfRows()-1, 0, 5));
Cell cell = row.createCell(0);
setCellValue(cell, strTypeDescription);
cell.setCellStyle(_style_3);
row = sheet.createRow(sheet.getPhysicalNumberOfRows());
}

public void createHeaderRow() {
Sheet sheet = _currentSheet;
Row row = sheet.createRow(sheet.getPhysicalNumberOfRows());
row.setHeight((short) 400);
for (int i = 0; i < 6; i++) {
row.createCell(i).setCellStyle(_style_4);
if (i == 2 || i == 3 || i == 4) {
sheet.setColumnWidth(i, 3500);
} else if (i == 5) {
sheet.setColumnWidth(i, 10000);
} else {
sheet.setColumnWidth(i, 8000);
}
}
Cell cell = row.getCell(0);
setCellValue(cell, "Data validation cells");
cell = row.getCell(1);
setCellValue(cell, "Condition");
cell = row.getCell(2);
setCellValue(cell, "Allow blank");
cell = row.getCell(3);
setCellValue(cell, "Prompt box");
cell = row.getCell(4);
setCellValue(cell, "Error box");
cell = row.getCell(5);
setCellValue(cell, "Other settings");
}

public ValidationAdder createValidationAdder(CellStyle cellStyle, int dataValidationType) {
return new ValidationAdder(_currentSheet, _style_1, _style_2, cellStyle, dataValidationType);
}

public void createDVDescriptionRow(String strTypeDescription) {
Sheet sheet = _currentSheet;
Row row = sheet.getRow(sheet.getPhysicalNumberOfRows()-1);
sheet.addMergedRegion(new CellRangeAddress(sheet.getPhysicalNumberOfRows()-1, sheet.getPhysicalNumberOfRows()-1, 0, 5));
Cell cell = row.createCell(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, Workbook 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
Sheet fSheet = wf.createSheet("Lists");
Sheet 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);
Name namedRange = wb.createName();
namedRange.setNameName("myName");
namedRange.setRefersToFormula(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++) {
Row currRow = fSheet.createRow(i + 29);
setCellValue(currRow.createCell(0), cellStrValue);
}
// add list data on another sheet
for (int i = 0; i < 10; i++) {
Row currRow = dataSheet.createRow(i + 0);
setCellValue(currRow.createCell(0), "Data a" + i);
setCellValue(currRow.createCell(1), "Data b" + i);
setCellValue(currRow.createCell(2), "Data c" + i);
}
}

private static void addDateTimeValidations(WorkbookFormatter wf, Workbook wb) {
wf.createSheet("Dates and Times");

DataFormat dataFormat = wb.createDataFormat();
short fmtDate = dataFormat.getFormat("m/d/yyyy");
short fmtTime = dataFormat.getFormat("h:mm");
CellStyle cellStyle_date = wb.createCellStyle();
cellStyle_date.setDataFormat(fmtDate);
CellStyle 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");
Workbook wb = _testDataProvider.createWorkbook();
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 !");

wb = _testDataProvider.writeOutAndReadBack(wb);
}



/* package */ static void setCellValue(Cell cell, String text) {
cell.setCellValue(text);

}

}

BIN
test-data/spreadsheet/DataValidations-49244.xlsx View File


Loading…
Cancel
Save