| /* ==================================================================== |
| 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.streaming; |
| |
| import java.text.DateFormat; |
| import java.text.SimpleDateFormat; |
| import java.time.LocalDateTime; |
| import java.util.Calendar; |
| import java.util.Date; |
| import java.util.Map; |
| |
| 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; |
| import org.apache.poi.ss.usermodel.DateUtil; |
| import org.apache.poi.ss.usermodel.FormulaError; |
| import org.apache.poi.ss.usermodel.Hyperlink; |
| import org.apache.poi.ss.usermodel.RichTextString; |
| 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.util.*; |
| import org.apache.poi.xssf.usermodel.XSSFHyperlink; |
| import org.apache.poi.xssf.usermodel.XSSFRichTextString; |
| |
| /** |
| * Streaming version of XSSFCell implementing the "BigGridDemo" strategy. |
| */ |
| public class SXSSFCell extends CellBase { |
| private final SXSSFRow _row; |
| private Value _value; |
| private CellStyle _style; |
| private Property _firstProperty; |
| |
| public SXSSFCell(SXSSFRow row, CellType cellType) |
| { |
| _row=row; |
| _value = new BlankValue(); |
| setType(cellType); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| protected SpreadsheetVersion getSpreadsheetVersion() { |
| return SpreadsheetVersion.EXCEL2007; |
| } |
| |
| /** |
| * Returns column index of this cell |
| * |
| * @return zero-based column index of a column in a sheet. |
| */ |
| @Override |
| public int getColumnIndex() |
| { |
| return _row.getCellIndex(this); |
| } |
| |
| /** |
| * Returns row index of a row in the sheet that contains this cell |
| * |
| * @return zero-based row index of a row in the sheet that contains this cell |
| */ |
| @Override |
| public int getRowIndex() |
| { |
| return _row.getRowNum(); |
| } |
| |
| /** |
| * Returns the sheet this cell belongs to |
| * |
| * @return the sheet this cell belongs to |
| */ |
| @Override |
| public SXSSFSheet getSheet() |
| { |
| return _row.getSheet(); |
| } |
| |
| /** |
| * Returns the Row this cell belongs to |
| * |
| * @return the Row that owns this cell |
| */ |
| @Override |
| public Row getRow() |
| { |
| return _row; |
| } |
| |
| @Override |
| protected void setCellTypeImpl(CellType cellType) { |
| ensureType(cellType); |
| } |
| |
| private boolean isFormulaCell() { |
| return _value instanceof FormulaValue; |
| } |
| |
| /** |
| * Return the cell type. |
| * |
| * @return the cell type |
| */ |
| @Override |
| public CellType getCellType() { |
| if (isFormulaCell()) { |
| return CellType.FORMULA; |
| } |
| |
| return _value.getType(); |
| } |
| |
| /** |
| * Only valid for formula cells |
| * @return one of ({@link CellType#NUMERIC}, {@link CellType#STRING}, |
| * {@link CellType#BOOLEAN}, {@link CellType#ERROR}) depending |
| * on the cached value of the formula |
| */ |
| @Override |
| public CellType getCachedFormulaResultType() { |
| if (!isFormulaCell()) { |
| throw new IllegalStateException("Only formula cells have cached results"); |
| } |
| |
| return ((FormulaValue)_value).getFormulaType(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setCellValueImpl(double value) { |
| ensureTypeOrFormulaType(CellType.NUMERIC); |
| if(_value.getType() == CellType.FORMULA) { |
| ((NumericFormulaValue) _value).setPreEvaluatedValue(value); |
| } else { |
| ((NumericValue)_value).setValue(value); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| protected void setCellValueImpl(Date value) { |
| boolean date1904 = getSheet().getWorkbook().isDate1904(); |
| setCellValue(DateUtil.getExcelDate(value, date1904)); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| protected void setCellValueImpl(LocalDateTime value) { |
| boolean date1904 = getSheet().getWorkbook().isDate1904(); |
| setCellValue(DateUtil.getExcelDate(value, date1904)); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| protected void setCellValueImpl(Calendar value) { |
| boolean date1904 = getSheet().getWorkbook().isDate1904(); |
| setCellValue( DateUtil.getExcelDate(value, date1904 )); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| protected void setCellValueImpl(RichTextString value) { |
| ensureRichTextStringType(); |
| |
| if(_value instanceof RichTextStringFormulaValue) { |
| ((RichTextStringFormulaValue) _value).setPreEvaluatedValue(value); |
| } else { |
| ((RichTextValue) _value).setValue(value); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| protected void setCellValueImpl(String value) { |
| ensureTypeOrFormulaType(CellType.STRING); |
| if(_value.getType() == CellType.FORMULA) { |
| ((StringFormulaValue) _value).setPreEvaluatedValue(value); |
| } else { |
| ((PlainStringValue) _value).setValue(value); |
| } |
| } |
| |
| /** |
| * 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)} |
| * </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 FormulaParseException if the formula has incorrect syntax or is otherwise invalid |
| */ |
| @Override |
| public void setCellFormulaImpl(String formula) throws FormulaParseException { |
| assert formula != null; |
| if (getCellType() == CellType.FORMULA) { |
| ((FormulaValue)_value).setValue(formula); |
| } else { |
| switch (getCellType()) { |
| case BLANK: |
| case NUMERIC: |
| _value = new NumericFormulaValue(formula, getNumericCellValue()); |
| break; |
| case STRING: |
| if (_value instanceof PlainStringValue) { |
| _value = new StringFormulaValue(formula, getStringCellValue()); |
| } else { |
| assert(_value instanceof RichTextValue); |
| _value = new RichTextStringFormulaValue(formula, ((RichTextValue) _value).getValue()); |
| } |
| break; |
| case BOOLEAN: |
| _value = new BooleanFormulaValue(formula, getBooleanCellValue()); |
| break; |
| case ERROR: |
| _value = new ErrorFormulaValue(formula, getErrorCellValue()); |
| break; |
| default: |
| throw new IllegalStateException("Cannot set a formula for a cell of type " + getCellType()); |
| } |
| } |
| } |
| |
| @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> |
| * |
| * @return a formula for the cell |
| * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is not CellType.FORMULA |
| */ |
| @Override |
| public String getCellFormula() |
| { |
| if(_value.getType()!=CellType.FORMULA) |
| throw typeMismatch(CellType.FORMULA,_value.getType(),false); |
| return ((FormulaValue)_value).getValue(); |
| } |
| |
| /** |
| * Get the value of the cell as a number. |
| * <p> |
| * For strings we throw an exception. For blank cells we return a 0. |
| * For formulas or error cells we return the precalculated value; |
| * </p> |
| * @return the value of the cell as a number |
| * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is CellType.STRING |
| * @exception NumberFormatException if the cell value isn't a parsable <code>double</code>. |
| * @see org.apache.poi.ss.usermodel.DataFormatter for turning this number into a string similar to that which Excel would render this number as. |
| */ |
| @Override |
| public double getNumericCellValue() |
| { |
| CellType cellType = getCellType(); |
| switch(cellType) |
| { |
| case BLANK: |
| return 0.0; |
| case FORMULA: |
| { |
| FormulaValue fv=(FormulaValue)_value; |
| if(fv.getFormulaType()!=CellType.NUMERIC) |
| throw typeMismatch(CellType.NUMERIC, CellType.FORMULA, false); |
| return ((NumericFormulaValue)_value).getPreEvaluatedValue(); |
| } |
| case NUMERIC: |
| return ((NumericValue)_value).getValue(); |
| default: |
| throw typeMismatch(CellType.NUMERIC, cellType, false); |
| } |
| } |
| |
| /** |
| * Get the value of the cell as a date. |
| * <p> |
| * For strings we throw an exception. For blank cells we return a null. |
| * </p> |
| * @return the value of the cell as a date |
| * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is CellType.STRING |
| * @exception NumberFormatException if the cell value isn't a parsable <code>double</code>. |
| * @see org.apache.poi.ss.usermodel.DataFormatter for formatting this date into a string similar to how excel does. |
| */ |
| @Override |
| public Date getDateCellValue() |
| { |
| CellType cellType = getCellType(); |
| if (cellType == CellType.BLANK) |
| { |
| return null; |
| } |
| |
| double value = getNumericCellValue(); |
| boolean date1904 = getSheet().getWorkbook().isDate1904(); |
| return DateUtil.getJavaDate(value, date1904); |
| } |
| |
| /** |
| * Get the value of the cell as a LocalDateTime. |
| * <p> |
| * For strings we throw an exception. For blank cells we return a null. |
| * </p> |
| * @return the value of the cell as a date |
| * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is CellType.STRING |
| * @exception NumberFormatException if the cell value isn't a parsable <code>double</code>. |
| * @see org.apache.poi.ss.usermodel.DataFormatter for formatting this date into a string similar to how excel does. |
| */ |
| @Override |
| public LocalDateTime getLocalDateTimeCellValue() { |
| if (getCellType() == CellType.BLANK) { |
| return null; |
| } |
| |
| double value = getNumericCellValue(); |
| boolean date1904 = getSheet().getWorkbook().isDate1904(); |
| return DateUtil.getLocalDateTime(value, date1904); |
| } |
| |
| /** |
| * Get the value of the cell as a XSSFRichTextString |
| * <p> |
| * For numeric cells we throw an exception. For blank cells we return an empty string. |
| * For formula cells we return the pre-calculated value if a string, otherwise an exception. |
| * </p> |
| * @return the value of the cell as a XSSFRichTextString |
| */ |
| @Override |
| public RichTextString getRichStringCellValue() |
| { |
| CellType cellType = getCellType(); |
| if(getCellType() != CellType.STRING) |
| throw typeMismatch(CellType.STRING, cellType, false); |
| |
| StringValue sval = (StringValue)_value; |
| if(sval.isRichText()) |
| return ((RichTextValue)_value).getValue(); |
| else { |
| String plainText = getStringCellValue(); |
| return getSheet().getWorkbook().getCreationHelper().createRichTextString(plainText); |
| } |
| } |
| |
| |
| /** |
| * Get the value of the cell as a string |
| * <p> |
| * For numeric cells we throw an exception. For blank cells we return an empty string. |
| * For formulaCells that are not string Formulas, we throw an exception. |
| * </p> |
| * @return the value of the cell as a string |
| */ |
| @Override |
| public String getStringCellValue() |
| { |
| CellType cellType = getCellType(); |
| switch(cellType) |
| { |
| case BLANK: |
| return ""; |
| case FORMULA: |
| { |
| FormulaValue fv=(FormulaValue)_value; |
| if(fv.getFormulaType()!=CellType.STRING) |
| throw typeMismatch(CellType.STRING, CellType.FORMULA, false); |
| if(_value instanceof RichTextStringFormulaValue) { |
| return ((RichTextStringFormulaValue) _value).getPreEvaluatedValue().getString(); |
| } else { |
| return ((StringFormulaValue) _value).getPreEvaluatedValue(); |
| } |
| } |
| case STRING: |
| { |
| if(((StringValue)_value).isRichText()) |
| return ((RichTextValue)_value).getValue().getString(); |
| else |
| return ((PlainStringValue)_value).getValue(); |
| } |
| default: |
| throw typeMismatch(CellType.STRING, cellType, false); |
| } |
| } |
| |
| /** |
| * Set a boolean value for the cell |
| * |
| * @param value the boolean value to set this cell to. For formulas we'll set the |
| * precalculated value, for booleans we'll set its value. For other types we |
| * will change the cell to a boolean cell and set its value. |
| */ |
| @Override |
| public void setCellValue(boolean value) |
| { |
| ensureTypeOrFormulaType(CellType.BOOLEAN); |
| if(_value.getType()==CellType.FORMULA) |
| ((BooleanFormulaValue)_value).setPreEvaluatedValue(value); |
| else |
| ((BooleanValue)_value).setValue(value); |
| } |
| |
| /** |
| * Set a error value for the cell |
| * |
| * @param value the error value to set this cell to. For formulas we'll set the |
| * precalculated value , for errors we'll set |
| * its value. For other types we will change the cell to an error |
| * cell and set its value. |
| * @see org.apache.poi.ss.usermodel.FormulaError |
| */ |
| @Override |
| public void setCellErrorValue(byte value) { |
| // for formulas, we want to keep the type and only have an ERROR as formula value |
| if(_value.getType()==CellType.FORMULA) { |
| _value = new ErrorFormulaValue(getCellFormula(), value); |
| } else { |
| _value = new ErrorValue(value); |
| } |
| } |
| |
| /** |
| * Get the value of the cell as a boolean. |
| * <p> |
| * For strings, numbers, and errors, we throw an exception. For blank cells we return a false. |
| * </p> |
| * @return the value of the cell as a boolean |
| * @throws IllegalStateException if the cell type returned by {@link #getCellType()} |
| * is not CellType.BOOLEAN, CellType.BLANK or CellType.FORMULA |
| */ |
| @Override |
| public boolean getBooleanCellValue() |
| { |
| CellType cellType = getCellType(); |
| switch(cellType) |
| { |
| case BLANK: |
| return false; |
| case FORMULA: |
| { |
| FormulaValue fv=(FormulaValue)_value; |
| if(fv.getFormulaType()!=CellType.BOOLEAN) |
| throw typeMismatch(CellType.BOOLEAN, CellType.FORMULA, false); |
| return ((BooleanFormulaValue)_value).getPreEvaluatedValue(); |
| } |
| case BOOLEAN: |
| { |
| return ((BooleanValue)_value).getValue(); |
| } |
| default: |
| throw typeMismatch(CellType.BOOLEAN, cellType, false); |
| } |
| } |
| |
| /** |
| * Get the value of the cell as an error code. |
| * <p> |
| * For strings, numbers, and booleans, we throw an exception. |
| * For blank cells we return a 0. |
| * </p> |
| * |
| * @return the value of the cell as an error code |
| * @throws IllegalStateException if the cell type returned by {@link #getCellType()} isn't CellType.ERROR |
| * @see org.apache.poi.ss.usermodel.FormulaError for error codes |
| */ |
| @Override |
| public byte getErrorCellValue() |
| { |
| CellType cellType = getCellType(); |
| switch(cellType) |
| { |
| case BLANK: |
| return 0; |
| case FORMULA: |
| { |
| FormulaValue fv=(FormulaValue)_value; |
| if(fv.getFormulaType()!=CellType.ERROR) |
| throw typeMismatch(CellType.ERROR, CellType.FORMULA, false); |
| return ((ErrorFormulaValue)_value).getPreEvaluatedValue(); |
| } |
| case ERROR: |
| { |
| return ((ErrorValue)_value).getValue(); |
| } |
| default: |
| throw typeMismatch(CellType.ERROR, cellType, false); |
| } |
| } |
| |
| /** |
| * <p>Set the style for the cell. The style should be an CellStyle created/retreived from |
| * the Workbook.</p> |
| * |
| * <p>To change the style of a cell without affecting other cells that use the same style, |
| * use {@link org.apache.poi.ss.util.CellUtil#setCellStyleProperties(Cell, Map)}</p> |
| * |
| * @param style reference contained in the workbook. |
| * If the value is null then the style information is removed causing the cell to used the default workbook style. |
| * @see org.apache.poi.ss.usermodel.Workbook#createCellStyle |
| */ |
| @Override |
| public void setCellStyle(CellStyle style) |
| { |
| _style=style; |
| } |
| |
| /** |
| * Return the cell's style. |
| * |
| * @return the cell's style. Always not-null. Default cell style has zero index and can be obtained as |
| * <code>workbook.getCellStyleAt(0)</code> |
| * @see org.apache.poi.ss.usermodel.Workbook#getCellStyleAt(int) |
| */ |
| @Override |
| public CellStyle getCellStyle() |
| { |
| if(_style == null){ |
| SXSSFWorkbook wb = (SXSSFWorkbook)getRow().getSheet().getWorkbook(); |
| return wb.getCellStyleAt(0); |
| } else { |
| return _style; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setAsActiveCell() |
| { |
| getSheet().setActiveCell(getAddress()); |
| } |
| |
| /** |
| * Assign a comment to this cell |
| * |
| * @param comment comment associated with this cell |
| */ |
| @Override |
| public void setCellComment(Comment comment) |
| { |
| setProperty(Property.COMMENT,comment); |
| } |
| |
| /** |
| * Returns comment associated with this cell |
| * |
| * @return comment associated with this cell or <code>null</code> if not found |
| */ |
| @Override |
| public Comment getCellComment() |
| { |
| return (Comment)getPropertyValue(Property.COMMENT); |
| } |
| |
| /** |
| * Removes the comment for this cell, if there is one. |
| */ |
| @Override |
| public void removeCellComment() |
| { |
| removeProperty(Property.COMMENT); |
| } |
| |
| /** |
| * @return hyperlink associated with this cell or <code>null</code> if not found |
| */ |
| @Override |
| public Hyperlink getHyperlink() |
| { |
| return (Hyperlink)getPropertyValue(Property.HYPERLINK); |
| } |
| |
| /** |
| * Assign a hyperlink to this cell. If the supplied hyperlink is null, the |
| * hyperlink for this cell will be removed. |
| * |
| * @param link hyperlink associated with this cell |
| */ |
| @Override |
| public void setHyperlink(Hyperlink link) |
| { |
| if (link == null) { |
| removeHyperlink(); |
| return; |
| } |
| |
| setProperty(Property.HYPERLINK,link); |
| |
| XSSFHyperlink xssfobj = (XSSFHyperlink)link; |
| // Assign to us |
| CellReference ref = new CellReference(getRowIndex(), getColumnIndex()); |
| xssfobj.setCellReference( ref ); |
| |
| // Add to the lists |
| getSheet()._sh.addHyperlink(xssfobj); |
| } |
| |
| /** |
| * Removes the hyperlink for this cell, if there is one. |
| */ |
| @Override |
| public void removeHyperlink() |
| { |
| removeProperty(Property.HYPERLINK); |
| |
| getSheet()._sh.removeHyperlink(getRowIndex(), getColumnIndex()); |
| } |
| |
| /** |
| * Only valid for array formula cells |
| * |
| * @return range of the array formula group that the cell belongs to. |
| */ |
| // TODO: What is this? |
| @NotImplemented |
| public CellRangeAddress getArrayFormulaRange() |
| { |
| return null; |
| } |
| |
| /** |
| * @return <code>true</code> if this cell is part of group of cells having a common array formula. |
| */ |
| //TODO: What is this? |
| @NotImplemented |
| public boolean isPartOfArrayFormulaGroup() |
| { |
| return false; |
| } |
| //end of interface implementation |
| |
| /** |
| * Returns a string representation of the cell |
| * <p> |
| * Formula cells return the formula string, rather than the formula result. |
| * Dates are displayed in dd-MMM-yyyy format |
| * Errors are displayed as #ERR<errIdx> |
| * </p> |
| */ |
| @Override |
| public String toString() { |
| switch (getCellType()) { |
| case BLANK: |
| return ""; |
| case BOOLEAN: |
| return getBooleanCellValue() ? "TRUE" : "FALSE"; |
| case ERROR: |
| return ErrorEval.getText(getErrorCellValue()); |
| case FORMULA: |
| return getCellFormula(); |
| case NUMERIC: |
| if (DateUtil.isCellDateFormatted(this)) { |
| DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale()); |
| sdf.setTimeZone(LocaleUtil.getUserTimeZone()); |
| return sdf.format(getDateCellValue()); |
| } |
| return getNumericCellValue() + ""; |
| case STRING: |
| return getRichStringCellValue().toString(); |
| default: |
| return "Unknown Cell Type: " + getCellType(); |
| } |
| } |
| |
| /*package*/ void removeProperty(int type) |
| { |
| Property current=_firstProperty; |
| Property previous=null; |
| while(current!=null&¤t.getType()!=type) |
| { |
| previous=current; |
| current=current._next; |
| } |
| if(current!=null) |
| { |
| if(previous!=null) |
| { |
| previous._next=current._next; |
| } |
| else |
| { |
| _firstProperty=current._next; |
| } |
| } |
| } |
| /*package*/ void setProperty(int type,Object value) |
| { |
| Property current=_firstProperty; |
| Property previous=null; |
| while(current!=null&¤t.getType()!=type) |
| { |
| previous=current; |
| current=current._next; |
| } |
| if(current!=null) |
| { |
| current.setValue(value); |
| } |
| else |
| { |
| switch(type) |
| { |
| case Property.COMMENT: |
| { |
| current=new CommentProperty(value); |
| break; |
| } |
| case Property.HYPERLINK: |
| { |
| current=new HyperlinkProperty(value); |
| break; |
| } |
| default: |
| { |
| throw new IllegalArgumentException("Invalid type: " + type); |
| } |
| } |
| if(previous!=null) |
| { |
| previous._next=current; |
| } |
| else |
| { |
| _firstProperty=current; |
| } |
| } |
| } |
| /*package*/ Object getPropertyValue(int type) |
| { |
| return getPropertyValue(type,null); |
| } |
| /*package*/ Object getPropertyValue(int type,String defaultValue) |
| { |
| Property current=_firstProperty; |
| while(current!=null&¤t.getType()!=type) current=current._next; |
| return current==null?defaultValue:current.getValue(); |
| } |
| /*package*/ void ensurePlainStringType() |
| { |
| if(_value.getType()!=CellType.STRING |
| ||((StringValue)_value).isRichText()) |
| _value = new PlainStringValue(); |
| } |
| /*package*/ void ensureRichTextStringType() |
| { |
| // don't change cell type for formulas |
| if(_value.getType() == CellType.FORMULA) { |
| String formula = ((FormulaValue)_value).getValue(); |
| _value = new RichTextStringFormulaValue(formula, new XSSFRichTextString("")); |
| } else if(_value.getType()!=CellType.STRING || |
| !((StringValue)_value).isRichText()) { |
| _value = new RichTextValue(); |
| } |
| } |
| /*package*/ void ensureType(CellType type) |
| { |
| if(_value.getType()!=type) |
| setType(type); |
| } |
| |
| /* |
| * Sets the cell type to type if it is different |
| */ |
| /*package*/ void ensureTypeOrFormulaType(CellType type) |
| { |
| if(_value.getType()==type) |
| { |
| if(type==CellType.STRING&&((StringValue)_value).isRichText()) |
| setType(CellType.STRING); |
| return; |
| } |
| if(_value.getType()==CellType.FORMULA) |
| { |
| if(((FormulaValue)_value).getFormulaType()==type) |
| return; |
| switch (type) { |
| case BOOLEAN: |
| _value = new BooleanFormulaValue(getCellFormula(), false); |
| break; |
| case NUMERIC: |
| _value = new NumericFormulaValue(getCellFormula(), 0); |
| break; |
| case STRING: |
| _value = new StringFormulaValue(getCellFormula(), ""); |
| break; |
| case ERROR: |
| _value = new ErrorFormulaValue(getCellFormula(), FormulaError._NO_ERROR.getCode()); |
| break; |
| default: |
| throw new AssertionError(); |
| } |
| return; |
| } |
| setType(type); |
| } |
| /** |
| * changes the cell type to the specified type, and resets the value to the default value for that type |
| * If cell type is the same as specified type, this will reset the value to the default value for that type |
| * |
| * @param type the cell type to set |
| * @throws IllegalArgumentException if type is not a recognized type |
| */ |
| /*package*/ void setType(CellType type) |
| { |
| switch(type) |
| { |
| case NUMERIC: |
| { |
| _value = new NumericValue(); |
| break; |
| } |
| case STRING: |
| { |
| PlainStringValue sval = new PlainStringValue(); |
| if(_value != null){ |
| // if a cell is not blank then convert the old value to string |
| String str = convertCellValueToString(); |
| sval.setValue(str); |
| } |
| _value = sval; |
| break; |
| } |
| case FORMULA: |
| { |
| if (getCellType() == CellType.BLANK) { |
| _value = new NumericFormulaValue("", 0); |
| } |
| break; |
| } |
| case BLANK: |
| { |
| _value = new BlankValue(); |
| break; |
| } |
| case BOOLEAN: |
| { |
| BooleanValue bval = new BooleanValue(); |
| if(_value != null){ |
| // if a cell is not blank then convert the old value to string |
| boolean val = convertCellValueToBoolean(); |
| bval.setValue(val); |
| } |
| _value = bval; |
| break; |
| } |
| case ERROR: |
| { |
| _value = new ErrorValue(); |
| break; |
| } |
| default: |
| { |
| throw new IllegalArgumentException("Illegal type " + type); |
| } |
| } |
| } |
| |
| //COPIED FROM https://svn.apache.org/repos/asf/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java since the functions are declared private there |
| /** |
| * Used to help format error messages |
| */ |
| private static IllegalStateException typeMismatch(CellType expectedTypeCode, CellType actualTypeCode, boolean isFormulaCell) { |
| String msg = "Cannot get a " + expectedTypeCode + " value from a " + actualTypeCode |
| + " " + (isFormulaCell ? "formula " : "") + "cell"; |
| return new IllegalStateException(msg); |
| } |
| |
| private boolean convertCellValueToBoolean() { |
| CellType cellType = getCellType(); |
| |
| if (cellType == CellType.FORMULA) { |
| cellType = getCachedFormulaResultType(); |
| } |
| |
| switch (cellType) { |
| case BOOLEAN: |
| return getBooleanCellValue(); |
| case STRING: |
| |
| String text = getStringCellValue(); |
| return Boolean.parseBoolean(text); |
| case NUMERIC: |
| return getNumericCellValue() != 0; |
| case ERROR: |
| case BLANK: |
| return false; |
| default: |
| throw new IllegalStateException("Unexpected cell type (" + cellType + ")"); |
| } |
| |
| } |
| private String convertCellValueToString() { |
| CellType cellType = getCellType(); |
| return convertCellValueToString(cellType); |
| } |
| private String convertCellValueToString(CellType cellType) { |
| switch (cellType) { |
| case BLANK: |
| return ""; |
| case BOOLEAN: |
| return getBooleanCellValue() ? "TRUE" : "FALSE"; |
| case STRING: |
| return getStringCellValue(); |
| case NUMERIC: |
| return Double.toString( getNumericCellValue() ); |
| case ERROR: |
| byte errVal = getErrorCellValue(); |
| return FormulaError.forInt(errVal).getString(); |
| case FORMULA: |
| if (_value != null) { |
| FormulaValue fv = (FormulaValue)_value; |
| if (fv.getFormulaType() != CellType.FORMULA) { |
| return convertCellValueToString(fv.getFormulaType()); |
| } |
| } |
| return ""; |
| default: |
| throw new IllegalStateException("Unexpected cell type (" + cellType + ")"); |
| } |
| } |
| |
| //END OF COPIED CODE |
| |
| static abstract class Property |
| { |
| static final int COMMENT=1; |
| static final int HYPERLINK=2; |
| Object _value; |
| Property _next; |
| public Property(Object value) |
| { |
| _value = value; |
| } |
| abstract int getType(); |
| void setValue(Object value) |
| { |
| _value = value; |
| } |
| Object getValue() |
| { |
| return _value; |
| } |
| } |
| static class CommentProperty extends Property |
| { |
| public CommentProperty(Object value) |
| { |
| super(value); |
| } |
| @Override |
| public int getType() |
| { |
| return COMMENT; |
| } |
| } |
| static class HyperlinkProperty extends Property |
| { |
| public HyperlinkProperty(Object value) |
| { |
| super(value); |
| } |
| @Override |
| public int getType() |
| { |
| return HYPERLINK; |
| } |
| } |
| interface Value |
| { |
| CellType getType(); |
| } |
| static class NumericValue implements Value { |
| double _value; |
| |
| public NumericValue() { |
| _value = 0; |
| } |
| |
| public NumericValue(double _value) { |
| this._value = _value; |
| } |
| |
| public CellType getType() |
| { |
| return CellType.NUMERIC; |
| } |
| void setValue(double value) |
| { |
| _value = value; |
| } |
| double getValue() |
| { |
| return _value; |
| } |
| } |
| static abstract class StringValue implements Value |
| { |
| public CellType getType() |
| { |
| return CellType.STRING; |
| } |
| //We cannot introduce a new type CellType.RICH_TEXT because the types are public so we have to make rich text as a type of string |
| abstract boolean isRichText(); // using the POI style which seems to avoid "instanceof". |
| } |
| static class PlainStringValue extends StringValue |
| { |
| String _value; |
| void setValue(String value) |
| { |
| _value = value; |
| } |
| String getValue() |
| { |
| return _value; |
| } |
| @Override |
| boolean isRichText() |
| { |
| return false; |
| } |
| } |
| static class RichTextValue extends StringValue |
| { |
| RichTextString _value; |
| @Override |
| public CellType getType() |
| { |
| return CellType.STRING; |
| } |
| void setValue(RichTextString value) |
| { |
| _value = value; |
| } |
| RichTextString getValue() |
| { |
| return _value; |
| } |
| @Override |
| boolean isRichText() |
| { |
| return true; |
| } |
| } |
| static abstract class FormulaValue implements Value |
| { |
| String _value; |
| |
| public FormulaValue(String _value) { |
| this._value = _value; |
| } |
| |
| public CellType getType() |
| { |
| return CellType.FORMULA; |
| } |
| void setValue(String value) |
| { |
| _value = value; |
| } |
| String getValue() |
| { |
| return _value; |
| } |
| abstract CellType getFormulaType(); |
| } |
| static class NumericFormulaValue extends FormulaValue { |
| double _preEvaluatedValue; |
| |
| public NumericFormulaValue(String formula, double _preEvaluatedValue) { |
| super(formula); |
| this._preEvaluatedValue = _preEvaluatedValue; |
| } |
| |
| @Override |
| CellType getFormulaType() |
| { |
| return CellType.NUMERIC; |
| } |
| void setPreEvaluatedValue(double value) |
| { |
| _preEvaluatedValue=value; |
| } |
| double getPreEvaluatedValue() |
| { |
| return _preEvaluatedValue; |
| } |
| } |
| static class StringFormulaValue extends FormulaValue { |
| String _preEvaluatedValue; |
| |
| public StringFormulaValue(String formula, String value) { |
| super(formula); |
| _preEvaluatedValue = value; |
| } |
| |
| @Override |
| CellType getFormulaType() |
| { |
| return CellType.STRING; |
| } |
| void setPreEvaluatedValue(String value) |
| { |
| _preEvaluatedValue=value; |
| } |
| String getPreEvaluatedValue() |
| { |
| return _preEvaluatedValue; |
| } |
| } |
| |
| static class RichTextStringFormulaValue extends FormulaValue { |
| RichTextString _preEvaluatedValue; |
| |
| public RichTextStringFormulaValue(String formula, RichTextString value) { |
| super(formula); |
| _preEvaluatedValue = value; |
| } |
| |
| @Override |
| CellType getFormulaType() |
| { |
| return CellType.STRING; |
| } |
| void setPreEvaluatedValue(RichTextString value) |
| { |
| _preEvaluatedValue=value; |
| } |
| RichTextString getPreEvaluatedValue() |
| { |
| return _preEvaluatedValue; |
| } |
| } |
| |
| static class BooleanFormulaValue extends FormulaValue { |
| boolean _preEvaluatedValue; |
| |
| public BooleanFormulaValue(String formula, boolean value) { |
| super(formula); |
| _preEvaluatedValue = value; |
| } |
| |
| @Override |
| CellType getFormulaType() |
| { |
| return CellType.BOOLEAN; |
| } |
| void setPreEvaluatedValue(boolean value) |
| { |
| _preEvaluatedValue=value; |
| } |
| boolean getPreEvaluatedValue() |
| { |
| return _preEvaluatedValue; |
| } |
| } |
| |
| static class ErrorFormulaValue extends FormulaValue { |
| byte _preEvaluatedValue; |
| |
| public ErrorFormulaValue(String formula, byte value) { |
| super(formula); |
| _preEvaluatedValue = value; |
| } |
| |
| @Override |
| CellType getFormulaType() |
| { |
| return CellType.ERROR; |
| } |
| void setPreEvaluatedValue(byte value) |
| { |
| _preEvaluatedValue=value; |
| } |
| byte getPreEvaluatedValue() |
| { |
| return _preEvaluatedValue; |
| } |
| } |
| |
| static class BlankValue implements Value { |
| public CellType getType() |
| { |
| return CellType.BLANK; |
| } |
| } |
| |
| static class BooleanValue implements Value { |
| boolean _value; |
| |
| public BooleanValue() { |
| _value = false; |
| } |
| |
| public BooleanValue(boolean _value) { |
| this._value = _value; |
| } |
| |
| public CellType getType() |
| { |
| return CellType.BOOLEAN; |
| } |
| void setValue(boolean value) |
| { |
| _value = value; |
| } |
| boolean getValue() |
| { |
| return _value; |
| } |
| } |
| static class ErrorValue implements Value |
| { |
| byte _value; |
| |
| public ErrorValue() { |
| _value = FormulaError._NO_ERROR.getCode(); |
| } |
| |
| public ErrorValue(byte _value) { |
| this._value = _value; |
| } |
| |
| public CellType getType() |
| { |
| return CellType.ERROR; |
| } |
| void setValue(byte value) |
| { |
| _value = value; |
| } |
| byte getValue() |
| { |
| return _value; |
| } |
| } |
| } |