From: Andreas Beeker
+ * CellType evaluatedCellType = evaluator.evaluateFormulaCell(cell);
+ *
+ * Be aware that your cell will hold both the formula, and the result. If you want the cell
+ * replaced with the result of the formula, use {@link #evaluateInCell(org.apache.poi.ss.usermodel.Cell)}
+ * @param cell The cell to evaluate
+ * @return {@link CellType#_NONE} for non-formula cells, or the type of the formula result
+ * @since POI 3.15 beta 3
+ * @deprecated POI 3.15 beta 3. Will be deleted when we make the CellType enum transition. See bug 59791.
+ */
+ @Internal
+ @Override
+ public CellType evaluateFormulaCellEnum(Cell cell) {
+ if (cell == null || cell.getCellTypeEnum() != CellType.FORMULA) {
+ return CellType._NONE;
+ }
+ CellValue cv = evaluateFormulaCellValue(cell);
+ // cell remains a formula cell, but the cached value is changed
+ setCellValue(cell, cv);
+ return cv.getCellType();
+ }
+
+ /**
+ * If cell contains formula, it evaluates the formula, and
+ * puts the formula result back into the cell, in place
+ * of the old formula.
+ * Else if cell does not contain formula, this method leaves
+ * the cell unchanged.
+ * Note that the same instance of HSSFCell is returned to
+ * allow chained calls like:
+ *
+ * int evaluatedCellType = evaluator.evaluateInCell(cell).getCellType();
+ *
+ * Be aware that your cell value will be changed to hold the
+ * result of the formula. If you simply want the formula
+ * value computed for you, use {@link #evaluateFormulaCellEnum(Cell)}}
+ */
@Override
public HSSFCell evaluateInCell(Cell cell) {
- return (HSSFCell) super.evaluateInCell(cell);
+ if (cell == null) {
+ return null;
+ }
+ HSSFCell result = (HSSFCell) cell;
+ if (cell.getCellTypeEnum() == CellType.FORMULA) {
+ CellValue cv = evaluateFormulaCellValue(cell);
+ setCellValue(cell, cv);
+ setCellType(cell, cv); // cell will no longer be a formula cell
+ }
+ return result;
+ }
+
+ private static void setCellValue(Cell cell, CellValue cv) {
+ CellType cellType = cv.getCellType();
+ switch (cellType) {
+ case BOOLEAN:
+ cell.setCellValue(cv.getBooleanValue());
+ break;
+ case ERROR:
+ cell.setCellErrorValue(cv.getErrorValue());
+ break;
+ case NUMERIC:
+ cell.setCellValue(cv.getNumberValue());
+ break;
+ case STRING:
+ cell.setCellValue(new HSSFRichTextString(cv.getStringValue()));
+ break;
+ case BLANK:
+ // never happens - blanks eventually get translated to zero
+ case FORMULA:
+ // this will never happen, we have already evaluated the formula
+ default:
+ throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
+ }
}
/**
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
index 2800904af1..b4339587b9 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
@@ -963,8 +963,9 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
* Get the HSSFSheet object at the given index.
* @param index of the sheet number (0-based physical & logical)
* @return HSSFSheet at the provided index
+ * @throws IllegalArgumentException if the index is out of range (index
+ * < 0 || index >= getNumberOfSheets()).
*/
-
@Override
public HSSFSheet getSheetAt(int index)
{
diff --git a/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java b/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java
index 47637daa3a..32a8701fb8 100644
--- a/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java
+++ b/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java
@@ -88,27 +88,26 @@ public class FileBackedDataSource extends DataSource {
throw new IndexOutOfBoundsException("Position " + position + " past the end of the file");
}
- // Do we read or map (for read/write?
+ // Do we read or map (for read/write)?
ByteBuffer dst;
- int worked = -1;
if (writable) {
dst = channel.map(FileChannel.MapMode.READ_WRITE, position, length);
- worked = 0;
- // remember the buffer for cleanup if necessary
- buffersToClean.add(dst);
+
+ // remember this buffer for cleanup
+ buffersToClean.add(dst);
} else {
- // Read
+ // allocate the buffer on the heap if we cannot map the data in directly
channel.position(position);
dst = ByteBuffer.allocate(length);
- worked = IOUtils.readFully(channel, dst);
- }
- // Check
- if(worked == -1) {
- throw new IndexOutOfBoundsException("Position " + position + " past the end of the file");
+ // Read the contents and check that we could read some data
+ int worked = IOUtils.readFully(channel, dst);
+ if(worked == -1) {
+ throw new IndexOutOfBoundsException("Position " + position + " past the end of the file");
+ }
}
- // Ready it for reading
+ // make it ready for reading
dst.position(0);
// All done
diff --git a/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java b/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java
index 9617877ca6..cb206051c0 100644
--- a/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java
+++ b/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java
@@ -84,7 +84,7 @@ public class Bin2Dec extends Fixed1ArgFunction implements FreeRefFunction {
//Add 1 to obtained number
sum++;
- value = "-" + String.valueOf(sum);
+ value = "-" + sum;
}
} catch (NumberFormatException e) {
return ErrorEval.NUM_ERROR;
diff --git a/src/java/org/apache/poi/ss/usermodel/CellStyle.java b/src/java/org/apache/poi/ss/usermodel/CellStyle.java
index df3d572598..1eab8dec19 100644
--- a/src/java/org/apache/poi/ss/usermodel/CellStyle.java
+++ b/src/java/org/apache/poi/ss/usermodel/CellStyle.java
@@ -26,308 +26,308 @@ public interface CellStyle {
* @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#GENERAL} instead.
*/
@Removal(version="3.17")
- static final short ALIGN_GENERAL = 0x0; //HorizontalAlignment.GENERAL.getCode();
+ short ALIGN_GENERAL = 0x0; //HorizontalAlignment.GENERAL.getCode();
/**
* left-justified horizontal alignment
* @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#LEFT} instead.
*/
@Removal(version="3.17")
- static final short ALIGN_LEFT = 0x1; //HorizontalAlignment.LEFT.getCode();
+ short ALIGN_LEFT = 0x1; //HorizontalAlignment.LEFT.getCode();
/**
* center horizontal alignment
* @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#CENTER} instead.
*/
@Removal(version="3.17")
- static final short ALIGN_CENTER = 0x2; //HorizontalAlignment.CENTER.getCode();
+ short ALIGN_CENTER = 0x2; //HorizontalAlignment.CENTER.getCode();
/**
* right-justified horizontal alignment
* @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#RIGHT} instead.
*/
@Removal(version="3.17")
- static final short ALIGN_RIGHT = 0x3; //HorizontalAlignment.RIGHT.getCode();
+ short ALIGN_RIGHT = 0x3; //HorizontalAlignment.RIGHT.getCode();
/**
* fill? horizontal alignment
* @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#FILL} instead.
*/
@Removal(version="3.17")
- static final short ALIGN_FILL = 0x4; //HorizontalAlignment.FILL.getCode();
+ short ALIGN_FILL = 0x4; //HorizontalAlignment.FILL.getCode();
/**
* justified horizontal alignment
* @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#JUSTIFY} instead.
*/
@Removal(version="3.17")
- static final short ALIGN_JUSTIFY = 0x5; //HorizontalAlignment.JUSTIFY.getCode();
+ short ALIGN_JUSTIFY = 0x5; //HorizontalAlignment.JUSTIFY.getCode();
/**
* center-selection? horizontal alignment
* @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#CENTER_SELECTION} instead.
*/
@Removal(version="3.17")
- static final short ALIGN_CENTER_SELECTION = 0x6; //HorizontalAlignment.CENTER_SELECTION.getCode();
+ short ALIGN_CENTER_SELECTION = 0x6; //HorizontalAlignment.CENTER_SELECTION.getCode();
/**
* top-aligned vertical alignment
* @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#TOP} instead.
*/
@Removal(version="3.17")
- static final short VERTICAL_TOP = 0x0; //VerticalAlignment.TOP.getCode();
+ short VERTICAL_TOP = 0x0; //VerticalAlignment.TOP.getCode();
/**
* center-aligned vertical alignment
* @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#CENTER} instead.
*/
@Removal(version="3.17")
- static final short VERTICAL_CENTER = 0x1; //VerticalAlignment.CENTER.getCode();
+ short VERTICAL_CENTER = 0x1; //VerticalAlignment.CENTER.getCode();
/**
* bottom-aligned vertical alignment
* @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#BOTTOM} instead.
*/
@Removal(version="3.17")
- static final short VERTICAL_BOTTOM = 0x2; //VerticalAlignment.BOTTOM.getCode();
+ short VERTICAL_BOTTOM = 0x2; //VerticalAlignment.BOTTOM.getCode();
/**
* vertically justified vertical alignment
* @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#JUSTIFY} instead.
*/
@Removal(version="3.17")
- static final short VERTICAL_JUSTIFY = 0x3; //VerticalAlignment.JUSTIFY.getCode();
+ short VERTICAL_JUSTIFY = 0x3; //VerticalAlignment.JUSTIFY.getCode();
/**
* No border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#NONE} instead.
*/
@Removal(version="3.17")
- static final short BORDER_NONE = 0x0; //BorderStyle.NONE.getCode();
+ short BORDER_NONE = 0x0; //BorderStyle.NONE.getCode();
/**
* Thin border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#THIN} instead.
*/
@Removal(version="3.17")
- static final short BORDER_THIN = 0x1; //BorderStyle.THIN.getCode();
+ short BORDER_THIN = 0x1; //BorderStyle.THIN.getCode();
/**
* Medium border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM} instead.
*/
@Removal(version="3.17")
- static final short BORDER_MEDIUM = 0x2; //BorderStyle.MEDIUM.getCode();
+ short BORDER_MEDIUM = 0x2; //BorderStyle.MEDIUM.getCode();
/**
* dash border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#DASHED} instead.
*/
@Removal(version="3.17")
- static final short BORDER_DASHED = 0x3; //BorderStyle.DASHED.getCode();
+ short BORDER_DASHED = 0x3; //BorderStyle.DASHED.getCode();
/**
* dot border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#DOTTED} instead.
*/
@Removal(version="3.17")
- static final short BORDER_DOTTED = 0x4; //BorderStyle.DOTTED.getCode();
+ short BORDER_DOTTED = 0x4; //BorderStyle.DOTTED.getCode();
/**
* Thick border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#THICK} instead.
*/
@Removal(version="3.17")
- static final short BORDER_THICK = 0x5; //BorderStyle.THICK.getCode();
+ short BORDER_THICK = 0x5; //BorderStyle.THICK.getCode();
/**
* double-line border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#DOUBLE} instead.
*/
@Removal(version="3.17")
- static final short BORDER_DOUBLE = 0x6; //BorderStyle.DOUBLE.getCode();
+ short BORDER_DOUBLE = 0x6; //BorderStyle.DOUBLE.getCode();
/**
* hair-line border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#HAIR} instead.
*/
@Removal(version="3.17")
- static final short BORDER_HAIR = 0x7; //BorderStyle.HAIR.getCode();
+ short BORDER_HAIR = 0x7; //BorderStyle.HAIR.getCode();
/**
* Medium dashed border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASHED} instead.
*/
@Removal(version="3.17")
- static final short BORDER_MEDIUM_DASHED = 0x8; //BorderStyle.MEDIUM_DASHED.getCode();
+ short BORDER_MEDIUM_DASHED = 0x8; //BorderStyle.MEDIUM_DASHED.getCode();
/**
* dash-dot border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#DASH_DOT} instead.
*/
@Removal(version="3.17")
- static final short BORDER_DASH_DOT = 0x9; //BorderStyle.DASH_DOT.getCode();
+ short BORDER_DASH_DOT = 0x9; //BorderStyle.DASH_DOT.getCode();
/**
* medium dash-dot border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASH_DOT} instead.
*/
@Removal(version="3.17")
- static final short BORDER_MEDIUM_DASH_DOT = 0xA; //BorderStyle.MEDIUM_DASH_DOT.getCode();
+ short BORDER_MEDIUM_DASH_DOT = 0xA; //BorderStyle.MEDIUM_DASH_DOT.getCode();
/**
* dash-dot-dot border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#DASH_DOT_DOT} instead.
*/
@Removal(version="3.17")
- static final short BORDER_DASH_DOT_DOT = 0xB; //BorderStyle.DASH_DOT_DOT.getCode();
+ short BORDER_DASH_DOT_DOT = 0xB; //BorderStyle.DASH_DOT_DOT.getCode();
/**
* medium dash-dot-dot border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASH_DOT_DOT} instead.
*/
@Removal(version="3.17")
- static final short BORDER_MEDIUM_DASH_DOT_DOT = 0xC; //BorderStyle.MEDIUM_DASH_DOT_DOT.getCode();
+ short BORDER_MEDIUM_DASH_DOT_DOT = 0xC; //BorderStyle.MEDIUM_DASH_DOT_DOT.getCode();
/**
* slanted dash-dot border
* @deprecated 3.15 beta 2. Use {@link BorderStyle#SLANTED_DASH_DOT} instead.
*/
@Removal(version="3.17")
- static final short BORDER_SLANTED_DASH_DOT = 0xD; //BorderStyle.SLANTED_DASH_DOT.getCode();
+ short BORDER_SLANTED_DASH_DOT = 0xD; //BorderStyle.SLANTED_DASH_DOT.getCode();
/**
* Fill Pattern: No background
* @deprecated 3.15 beta 3. Use {@link FillPatternType#NO_FILL} instead.
*/
@Removal(version="3.17")
- static final short NO_FILL = 0; //FillPatternType.NO_FILL.getCode();
+ short NO_FILL = 0; //FillPatternType.NO_FILL.getCode();
/**
* Fill Pattern: Solidly filled
* @deprecated 3.15 beta 3. Use {@link FillPatternType#SOLID_FOREGROUND} instead.
*/
@Removal(version="3.17")
- static final short SOLID_FOREGROUND = 1; //FillPatternType.SOLID_FOREGROUND.getCode();
+ short SOLID_FOREGROUND = 1; //FillPatternType.SOLID_FOREGROUND.getCode();
/**
* Fill Pattern: Small fine dots
* @deprecated 3.15 beta 3. Use {@link FillPatternType#FINE_DOTS} instead.
*/
@Removal(version="3.17")
- static final short FINE_DOTS = 2; //FillPatternType.FINE_DOTS.getCode();
+ short FINE_DOTS = 2; //FillPatternType.FINE_DOTS.getCode();
/**
* Fill Pattern: Wide dots
* @deprecated 3.15 beta 3. Use {@link FillPatternType#ALT_BARS} instead.
*/
@Removal(version="3.17")
- static final short ALT_BARS = 3; //FillPatternType.ALT_BARS.getCode();
+ short ALT_BARS = 3; //FillPatternType.ALT_BARS.getCode();
/**
* Fill Pattern: Sparse dots
* @deprecated 3.15 beta 3. Use {@link FillPatternType#SPARSE_DOTS} instead.
*/
@Removal(version="3.17")
- static final short SPARSE_DOTS = 4; //FillPatternType.SPARSE_DOTS.getCode();
+ short SPARSE_DOTS = 4; //FillPatternType.SPARSE_DOTS.getCode();
/**
* Fill Pattern: Thick horizontal bands
* @deprecated 3.15 beta 3. Use {@link FillPatternType#THICK_HORZ_BANDS} instead.
*/
@Removal(version="3.17")
- static final short THICK_HORZ_BANDS = 5; //FillPatternType.THICK_HORZ_BANDS.getCode();
+ short THICK_HORZ_BANDS = 5; //FillPatternType.THICK_HORZ_BANDS.getCode();
/**
* Fill Pattern: Thick vertical bands
* @deprecated 3.15 beta 3. Use {@link FillPatternType#THICK_VERT_BANDS} instead.
*/
@Removal(version="3.17")
- static final short THICK_VERT_BANDS = 6; //FillPatternType.THICK_VERT_BANDS.getCode();
+ short THICK_VERT_BANDS = 6; //FillPatternType.THICK_VERT_BANDS.getCode();
/**
* Fill Pattern: Thick backward facing diagonals
* @deprecated 3.15 beta 3. Use {@link FillPatternType#THICK_BACKWARD_DIAG} instead.
*/
@Removal(version="3.17")
- static final short THICK_BACKWARD_DIAG = 7; //FillPatternType.THICK_BACKWARD_DIAG.getCode();
+ short THICK_BACKWARD_DIAG = 7; //FillPatternType.THICK_BACKWARD_DIAG.getCode();
/**
* Fill Pattern: Thick forward facing diagonals
* @deprecated 3.15 beta 3. Use {@link FillPatternType#THICK_FORWARD_DIAG} instead.
*/
@Removal(version="3.17")
- static final short THICK_FORWARD_DIAG = 8; //FillPatternType.THICK_FORWARD_DIAG.getCode();
+ short THICK_FORWARD_DIAG = 8; //FillPatternType.THICK_FORWARD_DIAG.getCode();
/**
* Fill Pattern: Large spots
* @deprecated 3.15 beta 3. Use {@link FillPatternType#BIG_SPOTS} instead.
*/
@Removal(version="3.17")
- static final short BIG_SPOTS = 9; //FillPatternType.BIG_SPOTS.getCode();
+ short BIG_SPOTS = 9; //FillPatternType.BIG_SPOTS.getCode();
/**
* Fill Pattern: Brick-like layout
* @deprecated 3.15 beta 3. Use {@link FillPatternType#BRICKS} instead.
*/
@Removal(version="3.17")
- static final short BRICKS = 10; //FillPatternType.BRICKS.getCode();
+ short BRICKS = 10; //FillPatternType.BRICKS.getCode();
/**
* Fill Pattern: Thin horizontal bands
* @deprecated 3.15 beta 3. Use {@link FillPatternType#THIN_HORZ_BANDS} instead.
*/
@Removal(version="3.17")
- static final short THIN_HORZ_BANDS = 11; //FillPatternType.THIN_HORZ_BANDS.getCode();
+ short THIN_HORZ_BANDS = 11; //FillPatternType.THIN_HORZ_BANDS.getCode();
/**
* Fill Pattern: Thin vertical bands
* @deprecated 3.15 beta 3. Use {@link FillPatternType#THIN_VERT_BANDS} instead.
*/
@Removal(version="3.17")
- static final short THIN_VERT_BANDS = 12; //FillPatternType.THIN_VERT_BANDS.getCode();
+ short THIN_VERT_BANDS = 12; //FillPatternType.THIN_VERT_BANDS.getCode();
/**
* Fill Pattern: Thin backward diagonal
* @deprecated 3.15 beta 3. Use {@link FillPatternType#THIN_BACKWARD_DIAG} instead.
*/
@Removal(version="3.17")
- static final short THIN_BACKWARD_DIAG = 13; //FillPatternType.THIN_BACKWARD_DIAG.getCode();
+ short THIN_BACKWARD_DIAG = 13; //FillPatternType.THIN_BACKWARD_DIAG.getCode();
/**
* Fill Pattern: Thin forward diagonal
* @deprecated 3.15 beta 3. Use {@link FillPatternType#THIN_FORWARD_DIAG} instead.
*/
@Removal(version="3.17")
- static final short THIN_FORWARD_DIAG = 14; //FillPatternType.THIN_FORWARD_DIAG.getCode();
+ short THIN_FORWARD_DIAG = 14; //FillPatternType.THIN_FORWARD_DIAG.getCode();
/**
* Fill Pattern: Squares
* @deprecated 3.15 beta 3. Use {@link FillPatternType#SQUARES} instead.
*/
@Removal(version="3.17")
- static final short SQUARES = 15; //FillPatternType.SQUARES.getCode();
+ short SQUARES = 15; //FillPatternType.SQUARES.getCode();
/**
* Fill Pattern: Diamonds
* @deprecated 3.15 beta 3. Use {@link FillPatternType#DIAMONDS} instead.
*/
@Removal(version="3.17")
- static final short DIAMONDS = 16; //FillPatternType.DIAMONDS.getCode();
+ short DIAMONDS = 16; //FillPatternType.DIAMONDS.getCode();
/**
* Fill Pattern: Less Dots
* @deprecated 3.15 beta 3. Use {@link FillPatternType#LESS_DOTS} instead.
*/
@Removal(version="3.17")
- static final short LESS_DOTS = 17; //FillPatternType.LESS_DOTS.getCode();
+ short LESS_DOTS = 17; //FillPatternType.LESS_DOTS.getCode();
/**
* Fill Pattern: Least Dots
* @deprecated 3.15 beta 3. Use {@link FillPatternType#LEAST_DOTS} instead.
*/
@Removal(version="3.17")
- static final short LEAST_DOTS = 18; //FillPatternType.LEAST_DOTS.getCode();
+ short LEAST_DOTS = 18; //FillPatternType.LEAST_DOTS.getCode();
/**
* get the index within the Workbook (sequence within the collection of ExtnededFormat objects)
@@ -353,7 +353,7 @@ public interface CellStyle {
/**
* Get the format string
*/
- public String getDataFormatString();
+ String getDataFormatString();
/**
* set the font for this style
@@ -870,17 +870,17 @@ public interface CellStyle {
* to be of the same type (HSSFCellStyle or
* XSSFCellStyle)
*/
- public void cloneStyleFrom(CellStyle source);
+ void cloneStyleFrom(CellStyle source);
/**
* Controls if the Cell should be auto-sized
* to shrink to fit if the text is too long
*/
- public void setShrinkToFit(boolean shrinkToFit);
+ void setShrinkToFit(boolean shrinkToFit);
/**
* Should the Cell be auto-sized by Excel to shrink
* it to fit if this text is too long?
*/
- public boolean getShrinkToFit();
+ boolean getShrinkToFit();
}
diff --git a/src/java/org/apache/poi/ss/usermodel/CellValue.java b/src/java/org/apache/poi/ss/usermodel/CellValue.java
index 301accfca8..b10210882a 100644
--- a/src/java/org/apache/poi/ss/usermodel/CellValue.java
+++ b/src/java/org/apache/poi/ss/usermodel/CellValue.java
@@ -18,6 +18,8 @@
package org.apache.poi.ss.usermodel;
import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.Removal;
/**
* Mimics the 'data view' of a cell. This allows formula evaluator
@@ -47,12 +49,15 @@ public final class CellValue {
public CellValue(double numberValue) {
this(CellType.NUMERIC, numberValue, false, null, 0);
}
+
public static CellValue valueOf(boolean booleanValue) {
return booleanValue ? TRUE : FALSE;
}
+
public CellValue(String stringValue) {
this(CellType.STRING, 0.0, false, stringValue, 0);
}
+
public static CellValue getError(int errorCode) {
return new CellValue(CellType.ERROR, 0.0, false, null, errorCode);
}
@@ -64,30 +69,44 @@ public final class CellValue {
public boolean getBooleanValue() {
return _booleanValue;
}
+
/**
* @return Returns the numberValue.
*/
public double getNumberValue() {
return _numberValue;
}
+
/**
* @return Returns the stringValue.
*/
public String getStringValue() {
return _textValue;
}
+
+ /**
+ * Return the cell type.
+ *
+ * @return the cell type
+ * @since POI 3.15
+ * @deprecated POI 3.15
+ * Will be renamed to getCellTypeEnum()
when we make the CellType enum transition in POI 4.0. See bug 59791.
+ */
+ @Internal(since="POI 3.15 beta 3")
+ @Removal(version="4.2")
+ public CellType getCellTypeEnum() {
+ return _cellType;
+ }
+
/**
- * @return Returns the cellType.
- * @since POI 3.15
- */
- public CellType getCellTypeEnum() {
- return _cellType;
- }
- /**
- * @return Returns the cellType.
+ * Return the cell type.
+ *
+ * Will return {@link CellType} in version 4.0 of POI.
+ * For forwards compatibility, do not hard-code cell type literals in your code.
+ *
+ * @return the cell type
+ *
* @deprecated POI 3.15. Use {@link #getCellTypeEnum()} instead.
- * In the future, the signature of this method will be changed to return a
- * {@link CellType}.
*/
@Deprecated
public int getCellType() {
@@ -100,6 +119,7 @@ public final class CellValue {
public byte getErrorValue() {
return (byte) _errorCode;
}
+
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
diff --git a/src/java/org/apache/poi/ss/usermodel/Workbook.java b/src/java/org/apache/poi/ss/usermodel/Workbook.java
index e52615fb1a..f5043b727f 100644
--- a/src/java/org/apache/poi/ss/usermodel/Workbook.java
+++ b/src/java/org/apache/poi/ss/usermodel/Workbook.java
@@ -35,22 +35,22 @@ import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
public interface Workbook extends Closeable, Iterable
*/
+@Internal
public class NullLogger extends POILogger {
@Override
public void initialize(final String cat) {
@@ -37,7 +38,7 @@ public class NullLogger extends POILogger {
*/
@Override
- public void log(final int level, final Object obj1) {
+ protected void _log(final int level, final Object obj1) {
// do nothing
}
@@ -49,7 +50,19 @@ public class NullLogger extends POILogger {
* @param exception An exception to be logged
*/
@Override
- public void log(int level, Object obj1, final Throwable exception) {
+ protected void _log(int level, Object obj1, final Throwable exception) {
+ // do nothing
+ }
+
+ /**
+ * Log a message. Lazily appends Object parameters together.
+ * If the last parameter is a {@link Throwable} it is logged specially.
+ *
+ * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
+ * @param objs the objects to place in the message
+ */
+ @Override
+ public void log(int level, Object... objs) {
// do nothing
}
diff --git a/src/java/org/apache/poi/util/POILogFactory.java b/src/java/org/apache/poi/util/POILogFactory.java
index ba2551de7b..1e34ccd29b 100644
--- a/src/java/org/apache/poi/util/POILogFactory.java
+++ b/src/java/org/apache/poi/util/POILogFactory.java
@@ -35,7 +35,7 @@ public final class POILogFactory {
/**
* Map of POILogger instances, with classes as keys
*/
- private static Map
*
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL
*/
@@ -98,9 +107,9 @@ public abstract class POILogger {
// somehow this ambiguity works and doesn't lead to a loop,
// but it's confusing ...
if (lastEx == null) {
- log(level, msg);
+ _log(level, msg);
} else {
- log(level, msg, lastEx);
+ _log(level, msg, lastEx);
}
}
}
diff --git a/src/java/org/apache/poi/util/SystemOutLogger.java b/src/java/org/apache/poi/util/SystemOutLogger.java
index 36d96ca038..457f25410c 100644
--- a/src/java/org/apache/poi/util/SystemOutLogger.java
+++ b/src/java/org/apache/poi/util/SystemOutLogger.java
@@ -42,9 +42,9 @@ public class SystemOutLogger extends POILogger
* @param obj1 The object to log.
*/
@Override
- public void log(final int level, final Object obj1)
+ protected void _log(final int level, final Object obj1)
{
- log(level, obj1, null);
+ _log(level, obj1, null);
}
/**
@@ -56,7 +56,7 @@ public class SystemOutLogger extends POILogger
*/
@Override
@SuppressForbidden("uses printStackTrace")
- public void log(final int level, final Object obj1,
+ protected void _log(final int level, final Object obj1,
final Throwable exception) {
if (check(level)) {
System.out.println("[" + _cat + "]" + LEVEL_STRINGS_SHORT[Math.min(LEVEL_STRINGS_SHORT.length-1, level)] + " " + obj1);
diff --git a/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java b/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java
index a67e83e246..cdd35b3594 100644
--- a/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java
+++ b/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java
@@ -33,7 +33,6 @@ import org.apache.poi.hsmf.datatypes.AttachmentChunks;
import org.apache.poi.hsmf.extractor.OutlookTextExtactor;
import org.apache.poi.hssf.extractor.ExcelExtractor;
import org.apache.poi.hwpf.extractor.WordExtractor;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
@@ -123,7 +122,7 @@ public class ExtractorFactory {
return OLE2ExtractorFactory.getPreferEventExtractor();
}
- public static POITextExtractor createExtractor(File f) throws IOException, InvalidFormatException, OpenXML4JException, XmlException {
+ public static POITextExtractor createExtractor(File f) throws IOException, OpenXML4JException, XmlException {
NPOIFSFileSystem fs = null;
try {
fs = new NPOIFSFileSystem(f);
@@ -163,7 +162,7 @@ public class ExtractorFactory {
}
}
- public static POITextExtractor createExtractor(InputStream inp) throws IOException, InvalidFormatException, OpenXML4JException, XmlException {
+ public static POITextExtractor createExtractor(InputStream inp) throws IOException, OpenXML4JException, XmlException {
// Figure out the kind of stream
// If clearly doesn't do mark/reset, wrap up
if (! inp.markSupported()) {
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java
index 25efc1e559..6779d8a210 100644
--- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java
+++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java
@@ -64,7 +64,7 @@ public class SignatureConfig {
private static final POILogger LOG = POILogFactory.getLogger(SignatureConfig.class);
- public static interface SignatureConfigurable {
+ public interface SignatureConfigurable {
void setSignatureConfig(SignatureConfig signatureConfig);
}
diff --git a/src/ooxml/java/org/apache/poi/util/OOXMLLite.java b/src/ooxml/java/org/apache/poi/util/OOXMLLite.java
index b320771238..afb60f600e 100644
--- a/src/ooxml/java/org/apache/poi/util/OOXMLLite.java
+++ b/src/ooxml/java/org/apache/poi/util/OOXMLLite.java
@@ -96,6 +96,7 @@ public final class OOXMLLite {
"BaseTestXSheet",
"BaseTestXRow",
"BaseTestXCell",
+ "BaseTestXSSFPivotTable",
"TestSXSSFWorkbook\\$\\d",
"TestSXSSFWorkbook\\$NullOutputStream",
"TestUnfixedBugs",
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
index 0c4e4971d5..70df3f806a 100644
--- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
+++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
@@ -134,7 +134,7 @@ public abstract class XSLFShape implements Shape
+ * if (logger.check(POILogger.INFO)) {
+ * logger.log(POILogger.INFO, "Avoid concatenating " + " strings and evaluating " + functions());
+ * }
+ *
+ * CellType evaluatedCellType = evaluator.evaluateFormulaCellEnum(cell);
+ *
+ * Be aware that your cell will hold both the formula,
+ * and the result. If you want the cell replaced with
+ * the result of the formula, use {@link #evaluate(org.apache.poi.ss.usermodel.Cell)} }
+ * @param cell The cell to evaluate
+ * @return The type of the formula result (the cell's type remains as CellType.FORMULA however)
+ * If cell is not a formula cell, returns {@link CellType#_NONE} rather than throwing an exception.
+ * @since POI 3.15 beta 3
+ * @deprecated POI 3.15 beta 3. Will be deleted when we make the CellType enum transition. See bug 59791.
+ */
+ @Internal(since="POI 3.15 beta 3")
+ public CellType evaluateFormulaCellEnum(Cell cell) {
+ if (cell == null || cell.getCellTypeEnum() != CellType.FORMULA) {
+ return CellType._NONE;
+ }
+ CellValue cv = evaluateFormulaCellValue(cell);
+ // cell remains a formula cell, but the cached value is changed
+ setCellValue(cell, cv);
+ return cv.getCellType();
+ }
+
+ /**
+ * If cell contains formula, it evaluates the formula, and
+ * puts the formula result back into the cell, in place
+ * of the old formula.
+ * Else if cell does not contain formula, this method leaves
+ * the cell unchanged.
+ */
+ protected void doEvaluateInCell(Cell cell) {
+ if (cell == null) return;
+ if (cell.getCellTypeEnum() == CellType.FORMULA) {
+ CellValue cv = evaluateFormulaCellValue(cell);
+ setCellType(cell, cv); // cell will no longer be a formula cell
+ setCellValue(cell, cv);
+ }
+ }
+
+ private static void setCellValue(Cell cell, CellValue cv) {
+ CellType cellType = cv.getCellType();
+ switch (cellType) {
+ case BOOLEAN:
+ cell.setCellValue(cv.getBooleanValue());
+ break;
+ case ERROR:
+ cell.setCellErrorValue(cv.getErrorValue());
+ break;
+ case NUMERIC:
+ cell.setCellValue(cv.getNumberValue());
+ break;
+ case STRING:
+ cell.setCellValue(new XSSFRichTextString(cv.getStringValue()));
+ break;
+ case BLANK:
+ // never happens - blanks eventually get translated to zero
+ case FORMULA:
+ // this will never happen, we have already evaluated the formula
+ default:
+ throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
+ }
+ }
+
/**
* Turns a XSSFCell / SXSSFCell into a XSSFEvaluationCell
*/
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java
index 8ab465aff1..26735c782c 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java
@@ -28,10 +28,13 @@ import javax.xml.namespace.QName;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.Beta;
@@ -41,6 +44,7 @@ import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCacheField;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCacheFields;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotCacheDefinition;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheetSource;
public class XSSFPivotCacheDefinition extends POIXMLDocumentPart{
@@ -116,6 +120,40 @@ public class XSSFPivotCacheDefinition extends POIXMLDocumentPart{
out.close();
}
+ /**
+ * Find the 2D base data area for the pivot table, either from its direct reference or named table/range.
+ * @return AreaReference representing the current area defined by the pivot table
+ * @throws IllegalArgumentException if the ref attribute is not contiguous or the name attribute is not found.
+ */
+ @Beta
+ public AreaReference getPivotArea(Workbook wb) throws IllegalArgumentException {
+ final CTWorksheetSource wsSource = ctPivotCacheDefinition.getCacheSource().getWorksheetSource();
+
+ final String ref = wsSource.getRef();
+ final String name = wsSource.getName();
+
+ if (ref == null && name == null) throw new IllegalArgumentException("Pivot cache must reference an area, named range, or table.");
+
+ // this is the XML format, so tell the reference that.
+ if (ref != null) return new AreaReference(ref, SpreadsheetVersion.EXCEL2007);
+
+ if (name != null) {
+ // named range or table?
+ final Name range = wb.getName(name);
+ if (range != null) return new AreaReference(range.getRefersToFormula(), SpreadsheetVersion.EXCEL2007);
+ // not a named range, check for a table.
+ // do this second, as tables are sheet-specific, but named ranges are not, and may not have a sheet name given.
+ final XSSFSheet sheet = (XSSFSheet) wb.getSheet(wsSource.getSheet());
+ for (XSSFTable table : sheet.getTables()) {
+ if (table.getName().equals(name)) { //case-sensitive?
+ return new AreaReference(table.getStartCellReference(), table.getEndCellReference());
+ }
+ }
+ }
+
+ throw new IllegalArgumentException("Name '" + name + "' was not found.");
+ }
+
/**
* Generates a cache field for each column in the reference area for the pivot table.
* @param sheet The sheet where the data i collected from
@@ -123,7 +161,7 @@ public class XSSFPivotCacheDefinition extends POIXMLDocumentPart{
@Beta
protected void createCacheFields(Sheet sheet) {
//Get values for start row, start and end column
- AreaReference ar = new AreaReference(ctPivotCacheDefinition.getCacheSource().getWorksheetSource().getRef());
+ AreaReference ar = getPivotArea(sheet.getWorkbook());
CellReference firstCell = ar.getFirstCell();
CellReference lastCell = ar.getLastCell();
int columnStart = firstCell.getCol();
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java
index bf85f65de1..e6f91afde7 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java
@@ -30,11 +30,11 @@ import javax.xml.namespace.QName;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
-import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataConsolidateFunction;
import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.Beta;
@@ -214,13 +214,8 @@ public class XSSFPivotTable extends POIXMLDocumentPart {
}
protected AreaReference getPivotArea() {
- AreaReference pivotArea = new AreaReference(
- getPivotCacheDefinition()
- .getCTPivotCacheDefinition()
- .getCacheSource()
- .getWorksheetSource()
- .getRef(),
- SpreadsheetVersion.EXCEL2007);
+ final Workbook wb = getDataSheet().getWorkbook();
+ AreaReference pivotArea = getPivotCacheDefinition().getPivotArea(wb);
return pivotArea;
}
@@ -419,12 +414,13 @@ public class XSSFPivotTable extends POIXMLDocumentPart {
/**
* Creates cacheSource and workSheetSource for pivot table and sets the source reference as well assets the location of the pivot table
- * @param source Source for data for pivot table
* @param position Position for pivot table in sheet
* @param sourceSheet Sheet where the source will be collected from
+ * @param refConfig an configurator that knows how to configure pivot table references
*/
@Beta
- protected void createSourceReferences(AreaReference source, CellReference position, Sheet sourceSheet){
+ protected void createSourceReferences(CellReference position, Sheet sourceSheet, PivotTableReferenceConfigurator refConfig){
+
//Get cell one to the right and one down from position, add both to AreaReference and set pivot table location.
AreaReference destination = new AreaReference(position, new CellReference(position.getRow()+1, position.getCol()+1));
@@ -448,9 +444,8 @@ public class XSSFPivotTable extends POIXMLDocumentPart {
worksheetSource.setSheet(sourceSheet.getSheetName());
setDataSheet(sourceSheet);
- String[] firstCell = source.getFirstCell().getCellRefParts();
- String[] lastCell = source.getLastCell().getCellRefParts();
- worksheetSource.setRef(firstCell[2]+firstCell[1]+':'+lastCell[2]+lastCell[1]);
+ refConfig.configureReference(worksheetSource);
+ if (worksheetSource.getName() == null && worksheetSource.getRef() == null) throw new IllegalArgumentException("Pivot table source area reference or name must be specified.");
}
@Beta
@@ -465,11 +460,20 @@ public class XSSFPivotTable extends POIXMLDocumentPart {
int firstColumn = sourceArea.getFirstCell().getCol();
int lastColumn = sourceArea.getLastCell().getCol();
CTPivotField pivotField;
- for(int i = 0; i<=lastColumn-firstColumn; i++) {
+ for(int i = firstColumn; i<=lastColumn; i++) {
pivotField = pivotFields.addNewPivotField();
pivotField.setDataField(false);
pivotField.setShowAll(false);
}
pivotFields.setCount(pivotFields.sizeOfPivotFieldArray());
}
+
+ protected static interface PivotTableReferenceConfigurator {
+
+ /**
+ * Configure the name or area reference for the pivot table
+ * @param wsSource CTWorksheetSource that needs the pivot source reference assignment
+ */
+ public void configureReference(CTWorksheetSource wsSource);
+ }
}
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
index d72dca445e..bc2f071bea 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
@@ -64,8 +64,10 @@ import org.apache.poi.ss.usermodel.Footer;
import org.apache.poi.ss.usermodel.Header;
import org.apache.poi.ss.usermodel.IgnoredErrorType;
import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Table;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellAddress;
import org.apache.poi.ss.util.CellRangeAddress;
@@ -80,6 +82,7 @@ import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Removal;
import org.apache.poi.xssf.model.CommentsTable;
+import org.apache.poi.xssf.usermodel.XSSFPivotTable.PivotTableReferenceConfigurator;
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
import org.apache.poi.xssf.usermodel.helpers.XSSFIgnoredErrorHelper;
import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
@@ -1925,15 +1928,17 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
}
// Performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory
- final Integer rownumI = new Integer(row.getRowNum()); // NOSONAR
- int idx = _rows.headMap(rownumI).size();
- _rows.remove(rownumI);
+ final int rowNum = row.getRowNum();
+ final Integer rowNumI = new Integer(rowNum); // NOSONAR
+ // this is not the physical row number!
+ final int idx = _rows.headMap(rowNumI).size();
+ _rows.remove(rowNumI);
worksheet.getSheetData().removeRow(idx);
// also remove any comment located in that row
if(sheetComments != null) {
for (CellAddress ref : getCellComments().keySet()) {
- if (ref.getRow() == idx) {
+ if (ref.getRow() == rowNum) {
sheetComments.removeComment(ref);
}
}
@@ -4158,27 +4163,56 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
}
/**
- * Create a pivot table and set area of source, source sheet and a position for pivot table
- * @param source Area from where data will be collected
- * @param position A reference to the cell where the table will start
- * @param sourceSheet The sheet where source will be collected from
+ * Create a pivot table using the AreaReference range on sourceSheet, at the given position.
+ * If the source reference contains a sheet name, it must match the sourceSheet
+ * @param source location of pivot data
+ * @param position A reference to the top left cell where the pivot table will start
+ * @param sourceSheet The sheet containing the source data, if the source reference doesn't contain a sheet name
+ * @throws IllegalArgumentException if source references a sheet different than sourceSheet
* @return The pivot table
*/
@Beta
- public XSSFPivotTable createPivotTable(AreaReference source, CellReference position, Sheet sourceSheet) {
+ public XSSFPivotTable createPivotTable(final AreaReference source, CellReference position, Sheet sourceSheet) {
final String sourceSheetName = source.getFirstCell().getSheetName();
if(sourceSheetName != null && !sourceSheetName.equalsIgnoreCase(sourceSheet.getSheetName())) {
throw new IllegalArgumentException("The area is referenced in another sheet than the "
+ "defined source sheet " + sourceSheet.getSheetName() + ".");
}
+
+ return createPivotTable(position, sourceSheet, new PivotTableReferenceConfigurator() {
+ public void configureReference(CTWorksheetSource wsSource) {
+ final String[] firstCell = source.getFirstCell().getCellRefParts();
+ final String firstRow = firstCell[1];
+ final String firstCol = firstCell[2];
+ final String[] lastCell = source.getLastCell().getCellRefParts();
+ final String lastRow = lastCell[1];
+ final String lastCol = lastCell[2];
+ final String ref = firstCol+firstRow+':'+lastCol+lastRow; //or just source.formatAsString()
+ wsSource.setRef(ref);
+ }
+ });
+ }
+
+ /**
+ * Create a pivot table using the AreaReference or named/table range on sourceSheet, at the given position.
+ * If the source reference contains a sheet name, it must match the sourceSheet.
+ * @param sourceRef location of pivot data - mutually exclusive with SourceName
+ * @param sourceName range or table name for pivot data - mutually exclusive with SourceRef
+ * @param position A reference to the top left cell where the pivot table will start
+ * @param sourceSheet The sheet containing the source data, if the source reference doesn't contain a sheet name
+ * @throws IllegalArgumentException if source references a sheet different than sourceSheet
+ * @return The pivot table
+ */
+ private XSSFPivotTable createPivotTable(CellReference position, Sheet sourceSheet, PivotTableReferenceConfigurator refConfig) {
+
XSSFPivotTable pivotTable = createPivotTable();
//Creates default settings for the pivot table
pivotTable.setDefaultPivotTableDefinition();
//Set sources and references
- pivotTable.createSourceReferences(source, position, sourceSheet);
+ pivotTable.createSourceReferences(position, sourceSheet, refConfig);
- //Create cachefield/s and empty SharedItems
+ //Create cachefield/s and empty SharedItems - must be after creating references
pivotTable.getPivotCacheDefinition().createCacheFields(sourceSheet);
pivotTable.createDefaultDataColumns();
@@ -4186,9 +4220,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
}
/**
- * Create a pivot table and set area of source and a position for pivot table
- * @param source Area from where data will be collected
- * @param position A reference to the cell where the table will start
+ * Create a pivot table using the AreaReference range, at the given position.
+ * If the source reference contains a sheet name, that sheet is used, otherwise this sheet is assumed as the source sheet.
+ * @param source location of pivot data
+ * @param position A reference to the top left cell where the pivot table will start
* @return The pivot table
*/
@Beta
@@ -4201,6 +4236,57 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
return createPivotTable(source, position, this);
}
+ /**
+ * Create a pivot table using the Name range reference on sourceSheet, at the given position.
+ * If the source reference contains a sheet name, it must match the sourceSheet
+ * @param source location of pivot data
+ * @param position A reference to the top left cell where the pivot table will start
+ * @param sourceSheet The sheet containing the source data, if the source reference doesn't contain a sheet name
+ * @throws IllegalArgumentException if source references a sheet different than sourceSheet
+ * @return The pivot table
+ */
+ @Beta
+ public XSSFPivotTable createPivotTable(final Name source, CellReference position, Sheet sourceSheet) {
+ if(source.getSheetName() != null && !source.getSheetName().equals(sourceSheet.getSheetName())) {
+ throw new IllegalArgumentException("The named range references another sheet than the "
+ + "defined source sheet " + sourceSheet.getSheetName() + ".");
+ }
+
+ return createPivotTable(position, sourceSheet, new PivotTableReferenceConfigurator() {
+ public void configureReference(CTWorksheetSource wsSource) {
+ wsSource.setName(source.getNameName());
+ }
+ });
+ }
+
+ /**
+ * Create a pivot table using the Name range, at the given position.
+ * If the source reference contains a sheet name, that sheet is used, otherwise this sheet is assumed as the source sheet.
+ * @param source location of pivot data
+ * @param position A reference to the top left cell where the pivot table will start
+ * @return The pivot table
+ */
+ @Beta
+ public XSSFPivotTable createPivotTable(Name source, CellReference position) {
+ return createPivotTable(source, position, getWorkbook().getSheet(source.getSheetName()));
+ }
+
+ /**
+ * Create a pivot table using the Table, at the given position.
+ * Tables are required to have a sheet reference, so no additional logic around reference sheet is needed.
+ * @param source location of pivot data
+ * @param position A reference to the top left cell where the pivot table will start
+ * @return The pivot table
+ */
+ @Beta
+ public XSSFPivotTable createPivotTable(final Table source, CellReference position) {
+ return createPivotTable(position, getWorkbook().getSheet(source.getSheetName()), new PivotTableReferenceConfigurator() {
+ public void configureReference(CTWorksheetSource wsSource) {
+ wsSource.setName(source.getName());
+ }
+ });
+ }
+
/**
* Returns all the pivot tables for this Sheet
*/
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java
index 1e51e5e3f7..b27100656b 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java
@@ -319,6 +319,7 @@ public class ColumnHelper {
}
public int getIndexOfColumn(CTCols cols, CTCol searchCol) {
+ if (cols == null || searchCol == null) return -1;
int i = 0;
for (CTCol col : cols.getColArray()) {
if (col.getMin() == searchCol.getMin() && col.getMax() == searchCol.getMax()) {
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java
index d11ed1fa81..e55b014a7f 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java
@@ -147,7 +147,8 @@ public final class XSSFRowShifter extends RowShifter {
}
- if (f.isSetRef()) { //Range of cells which the formula applies to.
+ //Range of cells which the formula applies to.
+ if (f.isSetRef()) {
String ref = f.getRef();
String shiftedRef = shiftFormula(row, ref, shifter);
if (shiftedRef != null) f.setRef(shiftedRef);
diff --git a/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java b/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java
index 9d206f7197..26fe68a632 100644
--- a/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java
+++ b/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java
@@ -16,6 +16,7 @@
==================================================================== */
package org.apache.poi.extractor;
+import static org.apache.poi.POITestCase.assertContains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -37,6 +38,7 @@ import org.apache.poi.hdgf.extractor.VisioTextExtractor;
import org.apache.poi.hpbf.extractor.PublisherTextExtractor;
import org.apache.poi.hslf.extractor.PowerPointExtractor;
import org.apache.poi.hsmf.extractor.OutlookTextExtactor;
+import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.OldExcelFormatException;
import org.apache.poi.hssf.extractor.EventBasedExcelExtractor;
import org.apache.poi.hssf.extractor.ExcelExtractor;
@@ -1019,4 +1021,16 @@ public class TestExtractorFactory {
// expected here
}
}
+
+ // This bug is currently open. This test will fail with "expected error not thrown" when the bug has been fixed.
+ // When this happens, change this from @Test(expected=...) to @Test
+ // bug 45565: text within TextBoxes is extracted by ExcelExtractor and WordExtractor
+ @Test(expected=AssertionError.class)
+ public void test45565() throws Exception {
+ POITextExtractor extractor = ExtractorFactory.createExtractor(HSSFTestDataSamples.getSampleFile("45565.xls"));
+ String text = extractor.getText();
+ assertContains(text, "testdoc");
+ assertContains(text, "test phrase");
+ extractor.close();
+ }
}
diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java
index 77c91cdcae..202b9e18e9 100644
--- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java
+++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java
@@ -55,6 +55,7 @@ import org.apache.poi.POIDataSamples;
import org.apache.poi.POITestCase;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
+import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
import org.apache.poi.poifs.crypt.dsig.DigestInfo;
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
@@ -99,7 +100,7 @@ public class TestSignatureInfo {
public static void initBouncy() throws IOException {
CryptoFunctions.registerBouncyCastle();
- /*** TODO : set cal to now ... only set to fixed date for debugging ... */
+ // Set cal to now ... only set to fixed date for debugging ...
cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
assertNotNull(cal);
// cal.set(2014, 7, 6, 21, 42, 12);
@@ -403,7 +404,9 @@ public class TestSignatureInfo {
// verify
Iterator
+ * public static int add(int a, int b) {
+ * // a known bug in behavior that has not been fixed yet
+ * raise UnsupportedOperationException("add");
+ * }
+ *
+ * {@literal @}Test
+ * public void knownFailingUnitTest() {
+ * try {
+ * assertEquals(2, add(1,1));
+ * // this test fails because the assumption that this bug had not been fixed is false
+ * testPassesNow(12345);
+ * } catch (UnsupportedOperationException e) {
+ * // test is skipped because the assumption that this bug had not been fixed is true
+ * skipTest(e);
+ * }
+ * }
+ *
+ * Once passing, this unit test can be rewritten as:
+ * {@literal @}Test
+ * public void knownPassingUnitTest() {
+ * assertEquals(2, add(1,1));
+ * }
+ *
+ * If you have a better idea how to simplify test code while still notifying
+ * us when a previous known-failing test now passes, please improve these.
+ * As a bonus, a known-failing test that fails should not be counted as a
+ * passing test.
+ *
+ * One possible alternative is to expect the known exception, but without
+ * a clear message that it is a good thing to no longer get the expected
+ * exception once the test passes.
+ * {@literal @}Test(expected=UnsupportedOperationException.class)
+ * public void knownFailingUnitTest() {
+ * assertEquals(2, add(1,1));
+ * }
+ *
+ * @param e the exception that was caught that will no longer
+ * be raised when the bug is fixed
+ */
+ public static void skipTest(Throwable e) {
+ assumeTrue("This test currently fails with " + e, false);
+ }
+ /**
+ * @see #skipTest(Throwable)
+ *
+ * @param bug the bug number corresponding to a known bug in bugzilla
+ */
+ public static void testPassesNow(int bug) {
+ fail("This test passes now. Please update the unit test and bug " + bug + ".");
+ }
}
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
index 2ce6e1de8a..65042127e8 100644
--- a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
+++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
@@ -1885,12 +1885,12 @@ public final class TestBugs extends BaseTestBugzillaIssues {
// TODO - Fix these so they work...
/*row = s.getRow(4);
- assertEquals(CellType.FORMULA, row.getCell(1).getCellType());
+ assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
assertEquals("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.getCell(1).getCellFormula());
assertEquals(123.0, row.getCell(1).getNumericCellValue(), 0);
row = s.getRow(5);
- assertEquals(CellType.FORMULA, row.getCell(1).getCellType());
+ assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
assertEquals("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
assertEquals(234.0, row.getCell(1).getNumericCellValue(), 0);*/
diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSDocumentPath.java b/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSDocumentPath.java
index fef200fdcb..0ca0304381 100644
--- a/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSDocumentPath.java
+++ b/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSDocumentPath.java
@@ -227,7 +227,7 @@ public final class TestPOIFSDocumentPath extends TestCase {
{
for (int k = 0; k < paths.length; k++)
{
- assertEquals(String.valueOf(j) + "<>" + String.valueOf(k),
+ assertEquals(j + "<>" + k,
paths[ j ], paths[ k ]);
}
}
@@ -274,13 +274,13 @@ public final class TestPOIFSDocumentPath extends TestCase {
{
if (k == j)
{
- assertEquals(String.valueOf(j) + "<>"
- + String.valueOf(k), fullPaths[ j ],
+ assertEquals(j + "<>"
+ + k, fullPaths[ j ],
builtUpPaths[ k ]);
}
else
{
- assertTrue(String.valueOf(j) + "<>" + String.valueOf(k),
+ assertTrue(j + "<>" + k,
!(fullPaths[ j ].equals(builtUpPaths[ k ])));
}
}
@@ -306,7 +306,7 @@ public final class TestPOIFSDocumentPath extends TestCase {
{
for (int j = 0; j < badPaths.length; j++)
{
- assertTrue(String.valueOf(j) + "<>" + String.valueOf(k),
+ assertTrue(j + "<>" + k,
!(fullPaths[ k ].equals(badPaths[ j ])));
}
}
diff --git a/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java b/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java
index 2d98a4f38d..614b4effaf 100644
--- a/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java
+++ b/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java
@@ -18,10 +18,10 @@
package org.apache.poi.poifs.macros;
import static org.apache.poi.POITestCase.assertContains;
+import static org.apache.poi.POITestCase.skipTest;
+import static org.apache.poi.POITestCase.testPassesNow;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
import java.io.File;
import java.io.FileInputStream;
@@ -268,16 +268,28 @@ public class TestVBAMacroReader {
public void bug59858() throws IOException {
try {
fromFile(POIDataSamples.getSpreadSheetInstance(), "59858.xls");
- fail("This test passes now. Please update the unit test and bug 59858.");
+ testPassesNow(59858);
} catch (IOException e) {
if (e.getMessage().matches("Module offset for '.+' was never read.")) {
//e.printStackTrace();
// NPE when reading module.offset in VBAMacroReader.readMacros (approx line 258)
- assumeTrue("This test currently fails. See stdout.", false);
+ skipTest(e);
} else {
// something unexpected failed
throw e;
}
}
}
+
+ // This test is written as expected-to-fail and should be rewritten
+ // as expected-to-pass when the bug is fixed.
+ @Test
+ public void bug60158() throws IOException {
+ try {
+ fromFile(POIDataSamples.getDocumentInstance(), "60158.docm");
+ testPassesNow(60158);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ skipTest(e);
+ }
+ }
}
diff --git a/src/testcases/org/apache/poi/ss/formula/atp/TestIfError.java b/src/testcases/org/apache/poi/ss/formula/atp/TestIfError.java
index ebf6951f01..3a0a5b9b76 100644
--- a/src/testcases/org/apache/poi/ss/formula/atp/TestIfError.java
+++ b/src/testcases/org/apache/poi/ss/formula/atp/TestIfError.java
@@ -84,7 +84,7 @@ public class TestIfError extends TestCase {
assertEquals("Checks that the cell is numeric",
- CellType.STRING, evaluator.evaluate(cell2).getCellTypeEnum());
+ CellType.STRING, evaluator.evaluate(cell2).getCellTypeEnum());
assertEquals("Rounds -10 to a nearest multiple of -3 (-9)",
"Error in calculation", evaluator.evaluate(cell2).getStringValue());
diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java
index f9725ba8ae..7e41827a75 100644
--- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java
+++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java
@@ -33,12 +33,9 @@ import java.awt.font.FontRenderContext;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
-import java.io.FileInputStream;
import java.io.IOException;
import java.text.AttributedString;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import static org.junit.Assert.*;
diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java
index efae0d80c6..556e89b43a 100644
--- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java
+++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java
@@ -17,6 +17,8 @@
package org.apache.poi.ss.usermodel;
+import static org.apache.poi.POITestCase.skipTest;
+import static org.apache.poi.POITestCase.testPassesNow;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -295,7 +297,7 @@ public abstract class BaseTestSheetShiftRows {
wb.close();
}
- @Ignore("bug 56454: Incorrectly handles merged regions that do not contain column 0")
+ //@Ignore("bug 56454: Incorrectly handles merged regions that do not contain column 0")
@Test
public final void shiftWithMergedRegions_bug56454() throws IOException {
Workbook wb = _testDataProvider.createWorkbook();
@@ -328,7 +330,15 @@ public abstract class BaseTestSheetShiftRows {
expectedMergedRegions.add(A4_B8);
expectedMergedRegions.add(C4_D8);
- assertEquals(expectedMergedRegions, sheet.getMergedRegions());
+ // This test is written as expected-to-fail and should be rewritten
+ // as expected-to-pass when the bug is fixed.
+ // FIXME: remove try, catch, and testPassesNow, skipTest when test passes
+ try {
+ assertEquals(expectedMergedRegions, sheet.getMergedRegions());
+ testPassesNow(56454);
+ } catch (AssertionError e) {
+ skipTest(e);
+ }
wb.close();
}
@@ -589,7 +599,7 @@ public abstract class BaseTestSheetShiftRows {
read.close();
}
- @Ignore("bug 56454: Incorrectly handles merged regions that do not contain column 0")
+ //@Ignore("bug 56454: Incorrectly handles merged regions that do not contain column 0")
@Test
public void shiftRowsWithMergedRegionsThatDoNotContainColumnZero() throws IOException {
Workbook wb = _testDataProvider.createWorkbook();
@@ -614,9 +624,17 @@ public abstract class BaseTestSheetShiftRows {
// C5:D7 will be shifted down with same size
sheet.shiftRows(4, sheet.getLastRowNum(), 1);
- assertEquals(2, sheet.getNumMergedRegions());
- assertEquals(CellRangeAddress.valueOf("A4:B8"), sheet.getMergedRegion(0));
- assertEquals(CellRangeAddress.valueOf("C5:D8"), sheet.getMergedRegion(1));
+ // This test is written as expected-to-fail and should be rewritten
+ // as expected-to-pass when the bug is fixed.
+ // FIXME: remove try, catch, and testPassesNow, skipTest when test passes
+ try {
+ assertEquals(2, sheet.getNumMergedRegions());
+ assertEquals(CellRangeAddress.valueOf("A4:B8"), sheet.getMergedRegion(0));
+ assertEquals(CellRangeAddress.valueOf("C5:D8"), sheet.getMergedRegion(1));
+ testPassesNow(56454);
+ } catch (AssertionError e) {
+ skipTest(e);
+ }
wb.close();
}
diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetUpdateArrayFormulas.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetUpdateArrayFormulas.java
index 5e2ad4a8df..bbd95cccdc 100644
--- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetUpdateArrayFormulas.java
+++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetUpdateArrayFormulas.java
@@ -570,7 +570,7 @@ public abstract class BaseTestSheetUpdateArrayFormulas {
assertEquals(cra.formatAsString(), mcell.getArrayFormulaRange().formatAsString());
assertEquals("A2:A4*B2:B4", mcell.getCellFormula());
assertTrue(mcell.isPartOfArrayFormulaGroup());
- assertEquals(CellType.FORMULA, mcell.getCellType());
+ assertEquals(CellType.FORMULA, mcell.getCellTypeEnum());
}
*/
diff --git a/src/testcases/org/apache/poi/util/DummyPOILogger.java b/src/testcases/org/apache/poi/util/DummyPOILogger.java
index c8566fe663..7da48ce269 100644
--- a/src/testcases/org/apache/poi/util/DummyPOILogger.java
+++ b/src/testcases/org/apache/poi/util/DummyPOILogger.java
@@ -23,6 +23,7 @@ import java.util.List;
* POILogger which logs into an ArrayList, so that
* tests can see what got logged
*/
+@Internal
public class DummyPOILogger extends POILogger {
public List