mirror of https://github.com/apache/poi.git
unified setCellType(null/_NONE) logic, setCellFormula(null) logic. updated javadoc and tests
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1850676 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
81033fbad0
commit
f64aef7417
|
@ -43,6 +43,7 @@ import org.apache.poi.ss.formula.eval.ErrorEval;
|
|||
import org.apache.poi.ss.formula.ptg.ExpPtg;
|
||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellBase;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
|
@ -68,7 +69,7 @@ import org.apache.poi.util.Removal;
|
|||
* cells that have values should be added.
|
||||
* <p>
|
||||
*/
|
||||
public class HSSFCell implements Cell {
|
||||
public class HSSFCell extends CellBase {
|
||||
private static final String FILE_FORMAT_NAME = "BIFF8";
|
||||
/**
|
||||
* The maximum number of columns in BIFF8
|
||||
|
@ -255,17 +256,10 @@ public class HSSFCell implements Cell {
|
|||
return new CellAddress(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cells type (numeric, formula or string).
|
||||
* If the cell currently contains a value, the value will
|
||||
* be converted to match the new type, if possible.
|
||||
*/
|
||||
@Override
|
||||
public void setCellType(CellType cellType) {
|
||||
protected void setCellTypeImpl(CellType cellType) {
|
||||
notifyFormulaChanging();
|
||||
if(isPartOfArrayFormulaGroup()){
|
||||
notifyArrayFormulaChanging();
|
||||
}
|
||||
|
||||
int row=_record.getRow();
|
||||
short col=_record.getColumn();
|
||||
short styleIndex=_record.getXFIndex();
|
||||
|
@ -594,26 +588,21 @@ public class HSSFCell implements Cell {
|
|||
_stringValue.setUnicodeString(_book.getWorkbook().getSSTString(index));
|
||||
}
|
||||
|
||||
public void setCellFormula(String formula) {
|
||||
if(isPartOfArrayFormulaGroup()){
|
||||
notifyArrayFormulaChanging();
|
||||
}
|
||||
@Override
|
||||
protected void setCellFormulaImpl(String formula) {
|
||||
assert formula != null;
|
||||
|
||||
int row=_record.getRow();
|
||||
short col=_record.getColumn();
|
||||
short styleIndex=_record.getXFIndex();
|
||||
|
||||
if (formula==null) {
|
||||
notifyFormulaChanging();
|
||||
setCellType(CellType.BLANK, false, row, col, styleIndex);
|
||||
return;
|
||||
}
|
||||
int sheetIndex = _book.getSheetIndex(_sheet);
|
||||
Ptg[] ptgs = HSSFFormulaParser.parse(formula, _book, FormulaType.CELL, sheetIndex);
|
||||
setCellType(CellType.FORMULA, false, row, col, styleIndex);
|
||||
FormulaRecordAggregate agg = (FormulaRecordAggregate) _record;
|
||||
FormulaRecord frec = agg.getFormulaRecord();
|
||||
frec.setOptions((short) 2);
|
||||
|
||||
frec.setValue(0);
|
||||
|
||||
//only set to default if there is no extended format index already set
|
||||
|
@ -622,6 +611,42 @@ public class HSSFCell implements Cell {
|
|||
}
|
||||
agg.setParsedExpression(ptgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFormulaImpl() {
|
||||
assert getCellType() == CellType.FORMULA;
|
||||
|
||||
notifyFormulaChanging();
|
||||
|
||||
switch (getCachedFormulaResultType()) {
|
||||
case NUMERIC:
|
||||
double numericValue = ((FormulaRecordAggregate)_record).getFormulaRecord().getValue();
|
||||
_record = new NumberRecord();
|
||||
((NumberRecord)_record).setValue(numericValue);
|
||||
_cellType = CellType.NUMERIC;
|
||||
break;
|
||||
case STRING:
|
||||
_record = new NumberRecord();
|
||||
((NumberRecord)_record).setValue(0);
|
||||
_cellType = CellType.STRING;
|
||||
break;
|
||||
case BOOLEAN:
|
||||
boolean booleanValue = ((FormulaRecordAggregate)_record).getFormulaRecord().getCachedBooleanValue();
|
||||
_record = new BoolErrRecord();
|
||||
((BoolErrRecord)_record).setValue(booleanValue);
|
||||
_cellType = CellType.BOOLEAN;
|
||||
break;
|
||||
case ERROR:
|
||||
byte errorValue = (byte) ((FormulaRecordAggregate)_record).getFormulaRecord().getCachedErrorValue();
|
||||
_record = new BoolErrRecord();
|
||||
((BoolErrRecord)_record).setValue(errorValue);
|
||||
_cellType = CellType.ERROR;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called any time that a formula could potentially be deleted.
|
||||
* Does nothing if this cell currently does not hold a formula
|
||||
|
@ -1192,40 +1217,6 @@ public class HSSFCell implements Cell {
|
|||
return _cellType == CellType.FORMULA && ((FormulaRecordAggregate) _record).isPartOfArrayFormula();
|
||||
}
|
||||
|
||||
/**
|
||||
* The purpose of this method is to validate the cell state prior to modification
|
||||
*
|
||||
* @see #notifyArrayFormulaChanging()
|
||||
*/
|
||||
void notifyArrayFormulaChanging(String msg){
|
||||
CellRangeAddress cra = getArrayFormulaRange();
|
||||
if(cra.getNumberOfCells() > 1) {
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
//un-register the single-cell array formula from the parent XSSFSheet
|
||||
getRow().getSheet().removeArrayFormula(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this cell is modified.
|
||||
* <p>
|
||||
* The purpose of this method is to validate the cell state prior to modification.
|
||||
* </p>
|
||||
*
|
||||
* @see #setCellFormula(String)
|
||||
* @see HSSFRow#removeCell(org.apache.poi.ss.usermodel.Cell)
|
||||
* @see org.apache.poi.hssf.usermodel.HSSFSheet#removeRow(org.apache.poi.ss.usermodel.Row)
|
||||
* @see org.apache.poi.hssf.usermodel.HSSFSheet#shiftRows(int, int, int)
|
||||
* @see org.apache.poi.hssf.usermodel.HSSFSheet#addMergedRegion(org.apache.poi.ss.util.CellRangeAddress)
|
||||
* @throws IllegalStateException if modification is not allowed
|
||||
*/
|
||||
void notifyArrayFormulaChanging(){
|
||||
CellReference ref = new CellReference(this);
|
||||
String msg = "Cell "+ref.formatAsString()+" is part of a multi-cell array formula. " +
|
||||
"You cannot change part of an array.";
|
||||
notifyArrayFormulaChanging(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applying a user-defined style (UDS) is special. Excel does not directly reference user-defined styles, but
|
||||
* instead create a 'proxy' ExtendedFormatRecord referencing the UDS as parent.
|
||||
|
|
|
@ -164,7 +164,7 @@ public final class HSSFRow implements Row, Comparable<HSSFRow> {
|
|||
throw new RuntimeException("Specified cell is not from this row");
|
||||
}
|
||||
if(cell.isPartOfArrayFormulaGroup()){
|
||||
cell.notifyArrayFormulaChanging();
|
||||
cell.tryToDeleteArrayFormula(null);
|
||||
}
|
||||
|
||||
cells[column]=null;
|
||||
|
|
|
@ -299,7 +299,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
|
|||
HSSFCell xcell = (HSSFCell) cell;
|
||||
if (xcell.isPartOfArrayFormulaGroup()) {
|
||||
String msg = "Row[rownum=" + row.getRowNum() + "] contains cell(s) included in a multi-cell array formula. You cannot change part of an array.";
|
||||
xcell.notifyArrayFormulaChanging(msg);
|
||||
xcell.tryToDeleteArrayFormula(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1779,7 +1779,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
|
|||
for (Cell cell : row) {
|
||||
HSSFCell hcell = (HSSFCell) cell;
|
||||
if (hcell.isPartOfArrayFormulaGroup()) {
|
||||
hcell.notifyArrayFormulaChanging(msg);
|
||||
hcell.tryToDeleteArrayFormula(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,17 +70,22 @@ public interface Cell {
|
|||
Row getRow();
|
||||
|
||||
/**
|
||||
* Set the cells type (numeric, formula or string).
|
||||
* Set the cells type (blank, numeric, boolean, error or string).
|
||||
* <p>If the cell currently contains a value, the value will
|
||||
* be converted to match the new type, if possible. Formatting
|
||||
* is generally lost in the process however.</p>
|
||||
* <p>Conversion rules:</p>
|
||||
* <p>to NUMERIC: numeric value is left as is. True converts to 1.0, false converts to 0. otherwise, the
|
||||
* value is set to 0. Formula is removed.</p>
|
||||
* <p>If what you want to do is get a String value for your
|
||||
* numeric cell, <i>stop!</i>. This is not the way to do it.
|
||||
* Instead, for fetching the string value of a numeric or boolean
|
||||
* or date cell, use {@link DataFormatter} instead.</p>
|
||||
*
|
||||
* @throws IllegalArgumentException if the specified cell type is invalid
|
||||
* @throws IllegalStateException if the current value cannot be converted to the new type
|
||||
* <p>If cell is a member of an array formula group containing more than 1 cell, an {@link IllegalStateException}
|
||||
* is thrown. If the array formula group contains only this cell, it is removed</p>
|
||||
* @throws IllegalArgumentException if the specified cell type is invalid (null or _NONE)
|
||||
* @throws IllegalStateException if the current value cannot be converted to the new type or
|
||||
* if the cell is a part of an array formula group containing other cells
|
||||
*/
|
||||
void setCellType(CellType cellType);
|
||||
|
||||
|
@ -193,16 +198,33 @@ public interface Cell {
|
|||
|
||||
/**
|
||||
* Sets formula for this cell.
|
||||
*
|
||||
* <p>
|
||||
* Note, this method only sets the formula string and does not calculate the formula value.
|
||||
* To set the precalculated value use {@link #setCellValue(double)} or {@link #setCellValue(String)}
|
||||
* To set the precalculated value use {@link #setCellValue}
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If the cell was blank, sets value to 0. Otherwise, preserves the value as precalculated.
|
||||
* </p>
|
||||
*
|
||||
* @param formula the formula to set, e.g. <code>"SUM(C4:E4)"</code>.
|
||||
* If the argument is <code>null</code> then the current formula is removed.
|
||||
*
|
||||
* @throws IllegalStateException if this cell is a part of an array formula group containing other cells
|
||||
* @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid
|
||||
*/
|
||||
void setCellFormula(String formula) throws FormulaParseException;
|
||||
void setCellFormula(String formula) throws FormulaParseException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Removes formula, if any.
|
||||
*
|
||||
* If cell was blank, leaves it as is.
|
||||
* If it is a part of an array formula group, blanks the cell.
|
||||
* If has a regular formula, removes the formula preserving the "cached" value.
|
||||
* @throws IllegalStateException if cell is a part of an array formula group containing other cells
|
||||
*/
|
||||
void removeFormula() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Return a formula for the cell, for example, <code>SUM(C4:E4)</code>
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/* ====================================================================
|
||||
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.formula.FormulaParseException;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
|
||||
/**
|
||||
* Common implementation-independent logic shared by all implementations of {@link Cell}.
|
||||
* @author Vladislav "gallon" Galas gallon at apache dot org
|
||||
*/
|
||||
public abstract class CellBase implements Cell {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final void setCellType(CellType cellType) {
|
||||
if (cellType == null || cellType == CellType._NONE) {
|
||||
throw new IllegalArgumentException("cellType shall not be null nor _NONE");
|
||||
}
|
||||
|
||||
tryToDeleteArrayFormulaIfSet();
|
||||
|
||||
setCellTypeImpl(cellType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation-specific logic
|
||||
* @param cellType new cell type. Guaranteed non-null, not _NONE.
|
||||
*/
|
||||
protected abstract void setCellTypeImpl(CellType cellType);
|
||||
|
||||
/**
|
||||
* Called when this an array formula in this cell is deleted.
|
||||
* <p>The purpose of this method is to validate the cell state prior to modification.</p>
|
||||
*
|
||||
* @param message a customized exception message for the case if deletion of the cell is impossible. If null, a
|
||||
* default message will be generated
|
||||
* @see #setCellType(CellType)
|
||||
* @see #setCellFormula(String)
|
||||
* @see Row#removeCell(org.apache.poi.ss.usermodel.Cell)
|
||||
* @see org.apache.poi.ss.usermodel.Sheet#removeRow(org.apache.poi.ss.usermodel.Row)
|
||||
* @see org.apache.poi.ss.usermodel.Sheet#shiftRows(int, int, int)
|
||||
* @see org.apache.poi.ss.usermodel.Sheet#addMergedRegion(org.apache.poi.ss.util.CellRangeAddress)
|
||||
* @throws IllegalStateException if modification is not allowed
|
||||
*
|
||||
* Note. Exposing this to public is ugly. Needed for methods like Sheet#shiftRows.
|
||||
*/
|
||||
public final void tryToDeleteArrayFormula(String message) {
|
||||
assert isPartOfArrayFormulaGroup();
|
||||
|
||||
CellRangeAddress arrayFormulaRange = getArrayFormulaRange();
|
||||
if(arrayFormulaRange.getNumberOfCells() > 1) {
|
||||
if (message == null) {
|
||||
message = "Cell " + new CellReference(this).formatAsString() + " is part of a multi-cell array formula. " +
|
||||
"You cannot change part of an array.";
|
||||
}
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
//un-register the single-cell array formula from the parent sheet through public interface
|
||||
getRow().getSheet().removeArrayFormula(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final void setCellFormula(String formula) throws FormulaParseException, IllegalStateException {
|
||||
if (formula == null) {
|
||||
removeFormula();
|
||||
return;
|
||||
}
|
||||
|
||||
CellType previousValueType = getCellType() == CellType.FORMULA ? getCachedFormulaResultType() : getCellType();
|
||||
|
||||
tryToDeleteArrayFormulaIfSet();
|
||||
|
||||
setCellFormulaImpl(formula);
|
||||
|
||||
if (previousValueType == CellType.BLANK) {
|
||||
setCellValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation-specific setting the formula.
|
||||
* Shall not change the value.
|
||||
* @param formula
|
||||
*/
|
||||
protected abstract void setCellFormulaImpl(String formula);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final void removeFormula() {
|
||||
if (getCellType() == CellType.BLANK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPartOfArrayFormulaGroup()) {
|
||||
tryToDeleteArrayFormula(null);
|
||||
return;
|
||||
}
|
||||
|
||||
removeFormulaImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation-specific removal of the formula.
|
||||
* The cell is guaranteed to have a regular formula set.
|
||||
* Shall preserve the "cached" value.
|
||||
*/
|
||||
protected abstract void removeFormulaImpl();
|
||||
|
||||
private void tryToDeleteArrayFormulaIfSet() {
|
||||
if (isPartOfArrayFormulaGroup()) {
|
||||
tryToDeleteArrayFormula(null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import org.apache.poi.ss.SpreadsheetVersion;
|
|||
import org.apache.poi.ss.formula.FormulaParseException;
|
||||
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellBase;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
|
@ -45,7 +46,7 @@ import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
|||
/**
|
||||
* Streaming version of XSSFCell implementing the "BigGridDemo" strategy.
|
||||
*/
|
||||
public class SXSSFCell implements Cell {
|
||||
public class SXSSFCell extends CellBase {
|
||||
private final SXSSFRow _row;
|
||||
private Value _value;
|
||||
private CellStyle _style;
|
||||
|
@ -111,14 +112,8 @@ public class SXSSFCell implements Cell {
|
|||
return _row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cells type (numeric, formula or string)
|
||||
*
|
||||
* @throws IllegalArgumentException if the specified cell type is invalid
|
||||
*/
|
||||
@Override
|
||||
public void setCellType(CellType cellType)
|
||||
{
|
||||
protected void setCellTypeImpl(CellType cellType) {
|
||||
ensureType(cellType);
|
||||
}
|
||||
|
||||
|
@ -331,7 +326,7 @@ public class SXSSFCell implements Cell {
|
|||
* @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid
|
||||
*/
|
||||
@Override
|
||||
public void setCellFormula(String formula) throws FormulaParseException
|
||||
public void setCellFormulaImpl(String formula) throws FormulaParseException
|
||||
{
|
||||
if(formula == null) {
|
||||
setType(CellType.BLANK);
|
||||
|
@ -341,6 +336,36 @@ public class SXSSFCell implements Cell {
|
|||
ensureFormulaType(computeTypeFromFormula(formula));
|
||||
((FormulaValue)_value).setValue(formula);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFormulaImpl() {
|
||||
assert getCellType() == CellType.FORMULA;
|
||||
switch (getCachedFormulaResultType()) {
|
||||
case NUMERIC:
|
||||
double numericValue = ((NumericFormulaValue)_value).getPreEvaluatedValue();
|
||||
_value = new NumericValue();
|
||||
((NumericValue) _value).setValue(numericValue);
|
||||
break;
|
||||
case STRING:
|
||||
String stringValue = ((StringFormulaValue)_value).getPreEvaluatedValue();
|
||||
_value = new PlainStringValue();
|
||||
((PlainStringValue) _value).setValue(stringValue);
|
||||
break;
|
||||
case BOOLEAN:
|
||||
boolean booleanValue = ((BooleanFormulaValue)_value).getPreEvaluatedValue();
|
||||
_value = new BooleanValue();
|
||||
((BooleanValue) _value).setValue(booleanValue);
|
||||
break;
|
||||
case ERROR:
|
||||
byte errorValue = ((ErrorFormulaValue)_value).getPreEvaluatedValue();
|
||||
_value = new ErrorValue();
|
||||
((ErrorValue) _value).setValue(errorValue);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a formula for the cell, for example, <code>SUM(C4:E4)</code>
|
||||
*
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.apache.poi.ss.formula.SharedFormula;
|
|||
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellBase;
|
||||
import org.apache.poi.ss.usermodel.CellCopyPolicy;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
|
@ -70,7 +71,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
|
|||
* cells that have values should be added.
|
||||
* </p>
|
||||
*/
|
||||
public final class XSSFCell implements Cell {
|
||||
public final class XSSFCell extends CellBase {
|
||||
|
||||
private static final String FALSE_AS_STRING = "0";
|
||||
private static final String TRUE_AS_STRING = "1";
|
||||
|
@ -549,10 +550,7 @@ public final class XSSFCell implements Cell {
|
|||
* when the cell is a part of a multi-cell array formula
|
||||
*/
|
||||
@Override
|
||||
public void setCellFormula(String formula) {
|
||||
if(isPartOfArrayFormulaGroup()){
|
||||
notifyArrayFormulaChanging();
|
||||
}
|
||||
protected void setCellFormulaImpl(String formula) {
|
||||
setFormula(formula, FormulaType.CELL);
|
||||
}
|
||||
|
||||
|
@ -565,7 +563,7 @@ public final class XSSFCell implements Cell {
|
|||
|
||||
private void setFormula(String formula, FormulaType formulaType) {
|
||||
XSSFWorkbook wb = _row.getSheet().getWorkbook();
|
||||
if (formula == null) {
|
||||
if (formulaType == FormulaType.ARRAY && formula == null) {
|
||||
wb.onDeleteFormula(this);
|
||||
if (_cell.isSetF()) {
|
||||
_row.getSheet().onDeleteFormula(this, null);
|
||||
|
@ -597,6 +595,15 @@ public final class XSSFCell implements Cell {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFormulaImpl() {
|
||||
_row.getSheet().getWorkbook().onDeleteFormula(this);
|
||||
if (_cell.isSetF()) {
|
||||
_row.getSheet().onDeleteFormula(this, null);
|
||||
_cell.unsetF();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns column index of this cell
|
||||
*
|
||||
|
@ -960,13 +967,8 @@ public final class XSSFCell implements Cell {
|
|||
_cell.setR(ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cells type (numeric, formula or string)
|
||||
*
|
||||
* @throws IllegalArgumentException if the specified cell type is invalid
|
||||
*/
|
||||
@Override
|
||||
public void setCellType(CellType cellType) {
|
||||
protected void setCellTypeImpl(CellType cellType) {
|
||||
setCellType(cellType, null);
|
||||
}
|
||||
|
||||
|
@ -978,10 +980,6 @@ public final class XSSFCell implements Cell {
|
|||
*/
|
||||
protected void setCellType(CellType cellType, BaseXSSFEvaluationWorkbook evalWb) {
|
||||
CellType prevType = getCellType();
|
||||
|
||||
if(isPartOfArrayFormulaGroup()){
|
||||
notifyArrayFormulaChanging();
|
||||
}
|
||||
if(prevType == CellType.FORMULA && cellType != CellType.FORMULA) {
|
||||
if (_cell.isSetF()) {
|
||||
_row.getSheet().onDeleteFormula(this, evalWb);
|
||||
|
@ -1307,48 +1305,12 @@ public final class XSSFCell implements Cell {
|
|||
return getSheet().isCellInArrayFormulaContext(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* The purpose of this method is to validate the cell state prior to modification
|
||||
*
|
||||
* @see #notifyArrayFormulaChanging()
|
||||
*/
|
||||
void notifyArrayFormulaChanging(String msg){
|
||||
if(isPartOfArrayFormulaGroup()){
|
||||
CellRangeAddress cra = getArrayFormulaRange();
|
||||
if(cra.getNumberOfCells() > 1) {
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
//un-register the single-cell array formula from the parent XSSFSheet
|
||||
getRow().getSheet().removeArrayFormula(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this cell is modified.
|
||||
* <p>
|
||||
* The purpose of this method is to validate the cell state prior to modification.
|
||||
* </p>
|
||||
*
|
||||
* @see #setCellType(CellType)
|
||||
* @see #setCellFormula(String)
|
||||
* @see XSSFRow#removeCell(org.apache.poi.ss.usermodel.Cell)
|
||||
* @see org.apache.poi.xssf.usermodel.XSSFSheet#removeRow(org.apache.poi.ss.usermodel.Row)
|
||||
* @see org.apache.poi.xssf.usermodel.XSSFSheet#shiftRows(int, int, int)
|
||||
* @see org.apache.poi.xssf.usermodel.XSSFSheet#addMergedRegion(org.apache.poi.ss.util.CellRangeAddress)
|
||||
* @throws IllegalStateException if modification is not allowed
|
||||
*/
|
||||
void notifyArrayFormulaChanging(){
|
||||
CellReference ref = new CellReference(this);
|
||||
String msg = "Cell "+ref.formatAsString()+" is part of a multi-cell array formula. " +
|
||||
"You cannot change part of an array.";
|
||||
notifyArrayFormulaChanging(msg);
|
||||
}
|
||||
|
||||
|
||||
//Moved from XSSFRow.shift(). Not sure what is purpose.
|
||||
public void updateCellReferencesForShifting(String msg){
|
||||
if(isPartOfArrayFormulaGroup())
|
||||
notifyArrayFormulaChanging(msg);
|
||||
if(isPartOfArrayFormulaGroup()) {
|
||||
tryToDeleteArrayFormula(msg);
|
||||
}
|
||||
|
||||
CalculationChain calcChain = getSheet().getWorkbook().getCalculationChain();
|
||||
int sheetId = (int)getSheet().sheet.getSheetId();
|
||||
|
||||
|
|
|
@ -480,7 +480,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
|
||||
XSSFCell xcell = (XSSFCell)cell;
|
||||
if(xcell.isPartOfArrayFormulaGroup()) {
|
||||
xcell.notifyArrayFormulaChanging();
|
||||
xcell.setCellFormula(null); // to remove the array formula
|
||||
}
|
||||
if(cell.getCellType() == CellType.FORMULA) {
|
||||
_sheet.getWorkbook().onDeleteFormula(xcell);
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
|||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.xmlbeans.XmlCursor;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
|
||||
|
||||
|
@ -146,4 +147,35 @@ public class TestSXSSFCell extends BaseTestXCell {
|
|||
byte result = cell.getErrorCellValue();
|
||||
assertEquals(0, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, {@link SXSSFCell} doesn't support array formulas.
|
||||
* However, this test should be enabled if array formulas are implemented for SXSSF.
|
||||
*/
|
||||
@Override
|
||||
@Ignore
|
||||
public void setCellType_BLANK_removesArrayFormula_ifCellIsPartOfAnArrayFormulaGroupContainingOnlyThisCell() {
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, {@link SXSSFCell} doesn't support array formulas.
|
||||
* However, this test should be enabled if array formulas are implemented for SXSSF.
|
||||
*/
|
||||
@Override
|
||||
@Ignore
|
||||
@Test // <- annotation is necessary to override expected exception
|
||||
public void setCellType_BLANK_throwsISE_ifCellIsPartOfAnArrayFormulaGroupContainingOtherCells() {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Ignore
|
||||
@Test
|
||||
public void setCellFormula_throwsISE_ifCellIsPartOfAnArrayFormulaGroupContainingOtherCells() {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Ignore
|
||||
@Test
|
||||
public void removeFormula_turnsCellToBlank_whenFormulaWasASingleCellArrayFormula() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.poi.common.usermodel.HyperlinkType;
|
|||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.ITestDataProvider;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -1200,4 +1201,109 @@ public abstract class BaseTestCell {
|
|||
assertEquals(CellType.NUMERIC, cell.getCellType());
|
||||
assertEquals(value, cell.getNumericCellValue(), 0);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setCellType_null_throwsIAE() {
|
||||
Cell cell = getInstance();
|
||||
cell.setCellType(null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setCellType_NONE_throwsIAE() {
|
||||
Cell cell = getInstance();
|
||||
cell.setCellType(CellType._NONE);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void setCellType_BLANK_removesArrayFormula_ifCellIsPartOfAnArrayFormulaGroupContainingOnlyThisCell() {
|
||||
Cell cell = getInstance();
|
||||
|
||||
cell.getSheet().setArrayFormula("1", CellRangeAddress.valueOf("A1"));
|
||||
cell.setCellValue("foo");
|
||||
assertTrue(cell.isPartOfArrayFormulaGroup());
|
||||
assertEquals("1", cell.getCellFormula());
|
||||
|
||||
cell.setCellType(CellType.BLANK);
|
||||
|
||||
assertEquals(CellType.BLANK, cell.getCellType());
|
||||
assertFalse(cell.isPartOfArrayFormulaGroup());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void setCellType_BLANK_throwsISE_ifCellIsPartOfAnArrayFormulaGroupContainingOtherCells() {
|
||||
Cell cell = getInstance();
|
||||
cell.getSheet().setArrayFormula("1", CellRangeAddress.valueOf("A1:B1"));
|
||||
cell.setCellValue("foo");
|
||||
cell.setCellType(CellType.BLANK);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void setCellFormula_throwsISE_ifCellIsPartOfAnArrayFormulaGroupContainingOtherCells() {
|
||||
Cell cell = getInstance();
|
||||
|
||||
cell.getSheet().setArrayFormula("1", CellRangeAddress.valueOf("A1:B1"));
|
||||
assertTrue(cell.isPartOfArrayFormulaGroup());
|
||||
assertEquals(CellType.FORMULA, cell.getCellType());
|
||||
|
||||
cell.setCellFormula("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeFormula_preservesValue() {
|
||||
Cell cell = getInstance();
|
||||
|
||||
cell.setCellFormula("#DIV/0!");
|
||||
cell.setCellValue(true);
|
||||
cell.removeFormula();
|
||||
assertEquals(CellType.BOOLEAN, cell.getCellType());
|
||||
assertTrue(cell.getBooleanCellValue());
|
||||
|
||||
cell.setCellFormula("#DIV/0!");
|
||||
cell.setCellValue(2);
|
||||
cell.removeFormula();
|
||||
assertEquals(CellType.NUMERIC, cell.getCellType());
|
||||
assertEquals(2, cell.getNumericCellValue(), 0);
|
||||
|
||||
cell.setCellFormula("#DIV/0!");
|
||||
cell.setCellValue("foo");
|
||||
cell.removeFormula();
|
||||
assertEquals(CellType.STRING, cell.getCellType());
|
||||
assertEquals("foo", cell.getStringCellValue());
|
||||
|
||||
cell.setCellFormula("#DIV/0!");
|
||||
cell.setCellErrorValue(FormulaError.NUM.getCode());
|
||||
cell.removeFormula();
|
||||
assertEquals(CellType.ERROR, cell.getCellType());
|
||||
assertEquals(FormulaError.NUM.getCode(), cell.getErrorCellValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeFormula_turnsCellToBlank_whenFormulaWasASingleCellArrayFormula() {
|
||||
Cell cell = getInstance();
|
||||
|
||||
cell.getSheet().setArrayFormula("#DIV/0!", CellRangeAddress.valueOf("A1"));
|
||||
cell.setCellValue(true);
|
||||
cell.removeFormula();
|
||||
assertEquals(CellType.BLANK, cell.getCellType());
|
||||
|
||||
cell.getSheet().setArrayFormula("#DIV/0!", CellRangeAddress.valueOf("A1"));
|
||||
cell.setCellValue(2);
|
||||
cell.removeFormula();
|
||||
assertEquals(CellType.BLANK, cell.getCellType());
|
||||
|
||||
cell.getSheet().setArrayFormula("#DIV/0!", CellRangeAddress.valueOf("A1"));
|
||||
cell.setCellValue(true);
|
||||
cell.removeFormula();
|
||||
assertEquals(CellType.BLANK, cell.getCellType());
|
||||
|
||||
cell.getSheet().setArrayFormula("#DIV/0!", CellRangeAddress.valueOf("A1"));
|
||||
cell.setCellErrorValue(FormulaError.NUM.getCode());
|
||||
cell.removeFormula();
|
||||
assertEquals(CellType.BLANK, cell.getCellType());
|
||||
}
|
||||
|
||||
private Cell getInstance() {
|
||||
return _testDataProvider.createWorkbook().createSheet().createRow(0).createCell(0);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue