From 27f601e40e6bc2a5ac3eb759580106a569cbc0dc Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Mon, 22 Dec 2008 19:32:44 +0000 Subject: [PATCH] 1. added support for shared formulas in XSSF, see bug #464332. improved validation of workbook-global and sheet-global names git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@728749 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/changes.xml | 1 + src/documentation/content/xdocs/status.xml | 1 + .../poi/hssf/record/SharedFormulaRecord.java | 16 +- .../apache/poi/hssf/usermodel/HSSFName.java | 37 ++++- .../org/apache/poi/ss/usermodel/Name.java | 25 ++- .../apache/poi/xssf/usermodel/XSSFCell.java | 80 ++++++--- .../apache/poi/xssf/usermodel/XSSFName.java | 32 +++- .../apache/poi/xssf/usermodel/XSSFRow.java | 3 +- .../apache/poi/xssf/usermodel/XSSFSheet.java | 20 +++ .../usermodel/TestXSSFFormulaEvaluation.java | 155 ++++++++++-------- .../poi/xssf/usermodel/TestXSSFName.java | 49 ++++++ .../apache/poi/hssf/data/shared_formulas.xlsx | Bin 0 -> 10137 bytes .../hssf/record/TestSharedFormulaRecord.java | 57 +++++-- .../poi/hssf/usermodel/TestNamedRange.java | 51 ++++++ 14 files changed, 406 insertions(+), 121 deletions(-) create mode 100755 src/testcases/org/apache/poi/hssf/data/shared_formulas.xlsx diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 6ea6b15af7..2818057dab 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + 46433 - support for shared formulas in XSSF 46299 - support for carriage return and line break in XWPFRun 46300 - support for line spacing in XWPFParagraph 46308 - initial support for creation of XWPFTable diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 9d8f33e240..d9b6face6e 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 46433 - support for shared formulas in XSSF 46299 - support for carriage return and line break in XWPFRun 46300 - support for line spacing in XWPFParagraph 46308 - initial support for creation of XWPFTable diff --git a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java index f87c96f5a2..4878299981 100755 --- a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java @@ -17,11 +17,7 @@ package org.apache.poi.hssf.record; -import org.apache.poi.hssf.record.formula.AreaNPtg; -import org.apache.poi.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.hssf.record.formula.RefNPtg; -import org.apache.poi.hssf.record.formula.RefPtg; +import org.apache.poi.hssf.record.formula.*; import org.apache.poi.hssf.util.CellRangeAddress8Bit; import org.apache.poi.ss.formula.Formula; import org.apache.poi.util.HexDump; @@ -106,7 +102,7 @@ public final class SharedFormulaRecord extends SharedValueRecordBase { * Perhaps this functionality could be implemented in terms of the raw * byte array inside {@link Formula}. */ - static Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) { + public static Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) { Ptg[] newPtgStack = new Ptg[ptgs.length]; @@ -116,14 +112,14 @@ public final class SharedFormulaRecord extends SharedValueRecordBase { if (!ptg.isBaseToken()) { originalOperandClass = ptg.getPtgClass(); } - if (ptg instanceof RefNPtg) { - RefNPtg refNPtg = (RefNPtg)ptg; + if (ptg instanceof RefPtgBase) { + RefPtgBase refNPtg = (RefPtgBase)ptg; ptg = new RefPtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()), fixupRelativeColumn(formulaColumn,refNPtg.getColumn(),refNPtg.isColRelative()), refNPtg.isRowRelative(), refNPtg.isColRelative()); - } else if (ptg instanceof AreaNPtg) { - AreaNPtg areaNPtg = (AreaNPtg)ptg; + } else if (ptg instanceof AreaPtgBase) { + AreaPtgBase areaNPtg = (AreaPtgBase)ptg; ptg = new AreaPtg(fixupRelativeRow(formulaRow,areaNPtg.getFirstRow(),areaNPtg.isFirstRowRelative()), fixupRelativeRow(formulaRow,areaNPtg.getLastRow(),areaNPtg.isLastRowRelative()), fixupRelativeColumn(formulaColumn,areaNPtg.getFirstColumn(),areaNPtg.isFirstColRelative()), diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFName.java b/src/java/org/apache/poi/hssf/usermodel/HSSFName.java index f087f054cb..1865eaf0b8 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFName.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFName.java @@ -83,20 +83,49 @@ public final class HSSFName implements Name { * Names can contain uppercase and lowercase letters. * * + * + *

+ * A name must always be unique within its scope. POI prevents you from defining a name that is not unique + * within its scope. However you can use the same name in different scopes. Example: + *

+ * //by default names are workbook-global + * HSSFName name; + * name = workbook.createName(); + * name.setNameName("sales_08"); + * + * name = workbook.createName(); + * name.setNameName("sales_08"); //will throw an exception: "The workbook already contains this name (case-insensitive)" + * + * //create sheet-level name + * name = workbook.createName(); + * name.setSheetIndex(0); //the scope of the name is the first sheet + * name.setNameName("sales_08"); //ok + * + * name = workbook.createName(); + * name.setSheetIndex(0); + * name.setNameName("sales_08"); //will throw an exception: "The sheet already contains this name (case-insensitive)" + * + *
+ *

+ * * @param nameName named range name to set - * @throws IllegalArgumentException if the name is invalid or the workbook already contains this name (case-insensitive) + * @throws IllegalArgumentException if the name is invalid or the name already exists (case-insensitive) */ public void setNameName(String nameName){ - _definedNameRec.setNameText(nameName); Workbook wb = _book.getWorkbook(); + _definedNameRec.setNameText(nameName); + + int sheetNumber = _definedNameRec.getSheetNumber(); //Check to ensure no other names have the same case-insensitive name for ( int i = wb.getNumNames()-1; i >=0; i-- ) { NameRecord rec = wb.getNameRecord(i); if (rec != _definedNameRec) { - if (rec.getNameText().equalsIgnoreCase(getNameName())) - throw new IllegalArgumentException("The workbook already contains this name (case-insensitive)"); + if (rec.getNameText().equalsIgnoreCase(nameName) && sheetNumber == rec.getSheetNumber()){ + String msg = "The "+(sheetNumber == 0 ? "workbook" : "sheet")+" already contains this name: " + nameName; + throw new IllegalArgumentException(msg); + } } } } diff --git a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Name.java b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Name.java index 5f7b51543f..37eff5a422 100644 --- a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Name.java +++ b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Name.java @@ -87,8 +87,31 @@ public interface Name { * Names can contain uppercase and lowercase letters. * * + *

+ * A name must always be unique within its scope. POI prevents you from defining a name that is not unique + * within its scope. However you can use the same name in different scopes. Example: + *

+ * //by default names are workbook-global + * Name name; + * name = workbook.createName(); + * name.setNameName("sales_08"); + * + * name = workbook.createName(); + * name.setNameName("sales_08"); //will throw an exception: "The workbook already contains this name (case-insensitive)" + * + * //create sheet-level name + * name = workbook.createName(); + * name.setSheetIndex(0); //the scope of the name is the first sheet + * name.setNameName("sales_08"); //ok + * + * name = workbook.createName(); + * name.setSheetIndex(0); + * name.setNameName("sales_08"); //will throw an exception: "The sheet already contains this name (case-insensitive)" + * + *
+ *

* @param name named range name to set - * @throws IllegalArgumentException if the name is invalid or the workbook already contains this name (case-insensitive) + * @throws IllegalArgumentException if the name is invalid or the already exists within its scope (case-insensitive) */ void setNameName(String name); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java index bb3aafe07a..53db069108 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -24,16 +24,21 @@ import java.util.Date; import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.Ptg; +import org.apache.poi.hssf.record.SharedFormulaRecord; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaType; +import org.apache.poi.ss.formula.FormulaRenderer; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.POIXMLException; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType; /** * High level representation of a cell in a row of a spreadsheet. @@ -50,6 +55,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType; *

*/ public final class XSSFCell implements Cell { + private static POILogger logger = POILogFactory.getLogger(XSSFCell.class); /** * The maximum number of columns in SpreadsheetML @@ -108,7 +114,7 @@ public final class XSSFCell implements Cell { protected SharedStringsTable getSharedStringSource() { return sharedStringSource; } - + /** * @return table of cell styles shared across this workbook */ @@ -122,8 +128,8 @@ public final class XSSFCell implements Cell { * @return the sheet this cell belongs to */ public XSSFSheet getSheet() { - return getRow().getSheet(); - } + return getRow().getSheet(); + } /** * Returns the row this cell belongs to @@ -131,8 +137,8 @@ public final class XSSFCell implements Cell { * @return the row this cell belongs to */ public XSSFRow getRow() { - return row; - } + return row; + } /** * Get the value of the cell as a boolean. @@ -321,7 +327,31 @@ public final class XSSFCell implements Cell { int cellType = getCellType(); if(cellType != CELL_TYPE_FORMULA) throw typeMismatch(CELL_TYPE_FORMULA, cellType, false); - return this.cell.getF().getStringValue(); + CTCellFormula f = cell.getF(); + if(f.getT() == STCellFormulaType.SHARED){ + return convertSharedFormula((int)f.getSi()); + } else { + return f.getStringValue(); + } + } + + /** + * Creates a non shared formula from the shared formula counterpart + * + * @return non shared formula created for the given shared formula and this cell + */ + private String convertSharedFormula(int idx){ + XSSFSheet sheet = getSheet(); + XSSFCell sfCell = sheet.getSharedFormulaCell(idx); + if(sfCell == null){ + throw new IllegalStateException("Shared Formula not found for group index " + idx); + } + String sharedFormula = sfCell.getCTCell().getF().getStringValue(); + XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(sheet.getWorkbook()); + Ptg[] ptgs = FormulaParser.parse(sharedFormula, fpb); + Ptg[] fmla = SharedFormulaRecord.convertSharedFormulas(ptgs, + getRowIndex() - sfCell.getRowIndex(), getColumnIndex() - sfCell.getColumnIndex()); + return FormulaRenderer.toFormulaString(fpb, fmla); } /** @@ -363,7 +393,7 @@ public final class XSSFCell implements Cell { * @return zero-based column index of a column in a sheet. */ public int getColumnIndex() { - return this.cellNum; + return this.cellNum; } /** @@ -372,8 +402,8 @@ public final class XSSFCell implements Cell { * @return zero-based row index of a row in the sheet that contains this cell */ public int getRowIndex() { - return row.getRowNum(); - } + return row.getRowNum(); + } /** * Returns an A1 style reference to the location of this cell @@ -381,8 +411,8 @@ public final class XSSFCell implements Cell { * @return A1 style reference to the location of this cell */ public String getReference() { - return cell.getR(); - } + return cell.getR(); + } /** * Return the cell's style. @@ -406,8 +436,8 @@ public final class XSSFCell implements Cell { if(style == null) { if(cell.isSetS()) cell.unsetS(); } else { - XSSFCellStyle xStyle = (XSSFCellStyle)style; - xStyle.verifyBelongsToStylesSource(stylesSource); + XSSFCellStyle xStyle = (XSSFCellStyle)style; + xStyle.verifyBelongsToStylesSource(stylesSource); long idx = stylesSource.putStyle(xStyle); cell.setS(idx); @@ -486,7 +516,7 @@ public final class XSSFCell implements Cell { * will change the cell to a numeric cell and set its value. */ public void setCellValue(Date value) { - boolean date1904 = getSheet().getWorkbook().isDate1904(); + boolean date1904 = getSheet().getWorkbook().isDate1904(); setCellValue(DateUtil.getExcelDate(value, date1904)); } @@ -507,7 +537,7 @@ public final class XSSFCell implements Cell { * will change the cell to a numeric cell and set its value. */ public void setCellValue(Calendar value) { - boolean date1904 = getSheet().getWorkbook().isDate1904(); + boolean date1904 = getSheet().getWorkbook().isDate1904(); setCellValue( DateUtil.getExcelDate(value, date1904 )); } @@ -765,8 +795,8 @@ public final class XSSFCell implements Cell { * @return hyperlink associated with this cell or null if not found */ public XSSFHyperlink getHyperlink() { - return getSheet().getHyperlink(row.getRowNum(), cellNum); - } + return getSheet().getHyperlink(row.getRowNum(), cellNum); + } /** * Assign a hypelrink to this cell @@ -774,14 +804,14 @@ public final class XSSFCell implements Cell { * @param hyperlink the hypelrink to associate with this cell */ public void setHyperlink(Hyperlink hyperlink) { - XSSFHyperlink link = (XSSFHyperlink)hyperlink; - - // Assign to us - link.setCellReference( new CellReference(row.getRowNum(), cellNum).formatAsString() ); - - // Add to the lists - getSheet().setCellHyperlink(link); - } + XSSFHyperlink link = (XSSFHyperlink)hyperlink; + + // Assign to us + link.setCellReference( new CellReference(row.getRowNum(), cellNum).formatAsString() ); + + // Add to the lists + getSheet().setCellHyperlink(link); + } /** * Returns the xml bean containing information about the cell's location (reference), value, diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java index d9761a0014..85e919bef4 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java @@ -137,17 +137,45 @@ public final class XSSFName implements Name { * Sets the name that will appear in the user interface for the defined name. * Names must begin with a letter or underscore, not contain spaces and be unique across the workbook. * + *

+ * A name must always be unique within its scope. POI prevents you from defining a name that is not unique + * within its scope. However you can use the same name in different scopes. Example: + *

+ * //by default names are workbook-global + * XSSFName name; + * name = workbook.createName(); + * name.setNameName("sales_08"); + * + * name = workbook.createName(); + * name.setNameName("sales_08"); //will throw an exception: "The workbook already contains this name (case-insensitive)" + * + * //create sheet-level name + * name = workbook.createName(); + * name.setSheetIndex(0); //the scope of the name is the first sheet + * name.setNameName("sales_08"); //ok + * + * name = workbook.createName(); + * name.setSheetIndex(0); + * name.setNameName("sales_08"); //will throw an exception: "The sheet already contains this name (case-insensitive)" + * + *
+ *

* @param name name of this defined name * @throws IllegalArgumentException if the name is invalid or the workbook already contains this name (case-insensitive) */ public void setNameName(String name) { validateName(name); + int sheetIndex = getSheetIndex(); + //Check to ensure no other names have the same case-insensitive name for (int i = 0; i < workbook.getNumberOfNames(); i++) { XSSFName nm = workbook.getNameAt(i); - if (nm != this && nm.getNameName().equalsIgnoreCase(name)) { - throw new IllegalArgumentException("The workbook already contains this name: " + name); + if (nm != this) { + if(name.equalsIgnoreCase(nm.getNameName()) && sheetIndex == nm.getSheetIndex()){ + String msg = "The "+(sheetIndex == -1 ? "workbook" : "sheet")+" already contains this name: " + name; + throw new IllegalArgumentException(msg); + } } } ctName.setName(name); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java index d402eed4fc..9de3ea46cb 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java @@ -63,7 +63,8 @@ public class XSSFRow implements Row, Comparable { this.cells = new TreeMap(); for (CTCell c : row.getCArray()) { XSSFCell cell = new XSSFCell(this, c); - this.cells.put(cell.getColumnIndex(), cell); + cells.put(cell.getColumnIndex(), cell); + sheet.onReadCell(cell); } } 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 d2f781bb27..c8de77972d 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -74,6 +74,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { private List hyperlinks; private ColumnHelper columnHelper; private CommentsTable sheetComments; + private Map sharedFormulas; /** * Creates new XSSFSheet - called by XSSFWorkbook to create a sheet from scratch. @@ -147,6 +148,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { private void initRows(CTWorksheet worksheet) { rows = new TreeMap(); + sharedFormulas = new HashMap(); for (CTRow row : worksheet.getSheetData().getRowArray()) { XSSFRow r = new XSSFRow(row, this); rows.put(r.getRowNum(), r); @@ -1664,6 +1666,24 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { return getDefaultSheetView().getPane(); } + /** + * Return a cell holding shared formula by shared group index + * + * @param sid shared group index + * @return a cell holding shared formula or null if not found + */ + XSSFCell getSharedFormulaCell(int sid){ + return sharedFormulas.get(sid); + } + + void onReadCell(XSSFCell cell){ + //collect cells holding shared formulas + CTCell ct = cell.getCTCell(); + CTCellFormula f = ct.getF(); + if(f != null && f.getT() == STCellFormulaType.SHARED && f.isSetRef() && f.getStringValue() != null){ + sharedFormulas.put((int)f.getSi(), cell); + } + } @Override protected void commit() throws IOException { diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java index 668e83a0e2..b9035db6b2 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java @@ -19,83 +19,106 @@ package org.apache.poi.xssf.usermodel; import junit.framework.TestCase; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.FormulaEvaluator; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.XSSFTestDataSamples; public final class TestXSSFFormulaEvaluation extends TestCase { - public TestXSSFFormulaEvaluation(String name) { - super(name); - - // Use system out logger - System.setProperty( - "org.apache.poi.util.POILogger", - "org.apache.poi.util.SystemOutLogger" - ); - } - - public void testSimpleArithmatic() { - XSSFWorkbook wb = new XSSFWorkbook(); - Sheet s = wb.createSheet(); - Row r = s.createRow(0); - - Cell c1 = r.createCell(0); - c1.setCellFormula("1+5"); - assertEquals(0.0, c1.getNumericCellValue() ); - - Cell c2 = r.createCell(1); - c2.setCellFormula("10/2"); + public TestXSSFFormulaEvaluation(String name) { + super(name); + + // Use system out logger + System.setProperty( + "org.apache.poi.util.POILogger", + "org.apache.poi.util.SystemOutLogger" + ); + } + + public void testSimpleArithmatic() { + XSSFWorkbook wb = new XSSFWorkbook(); + Sheet s = wb.createSheet(); + Row r = s.createRow(0); + + Cell c1 = r.createCell(0); + c1.setCellFormula("1+5"); + assertEquals(0.0, c1.getNumericCellValue() ); + + Cell c2 = r.createCell(1); + c2.setCellFormula("10/2"); assertEquals(0.0, c2.getNumericCellValue() ); - FormulaEvaluator fe = new XSSFFormulaEvaluator(wb); - - fe.evaluateFormulaCell(c1); - fe.evaluateFormulaCell(c2); - - assertEquals(6.0, c1.getNumericCellValue(), 0.0001); - assertEquals(5.0, c2.getNumericCellValue(), 0.0001); - } - - public void testSumCount() { - XSSFWorkbook wb = new XSSFWorkbook(); - Sheet s = wb.createSheet(); - Row r = s.createRow(0); - r.createCell(0).setCellValue(2.5); - r.createCell(1).setCellValue(1.1); - r.createCell(2).setCellValue(3.2); - r.createCell(4).setCellValue(10.7); - - r = s.createRow(1); - - Cell c1 = r.createCell(0); - c1.setCellFormula("SUM(A1:B1)"); + FormulaEvaluator fe = new XSSFFormulaEvaluator(wb); + + fe.evaluateFormulaCell(c1); + fe.evaluateFormulaCell(c2); + + assertEquals(6.0, c1.getNumericCellValue(), 0.0001); + assertEquals(5.0, c2.getNumericCellValue(), 0.0001); + } + + public void testSumCount() { + XSSFWorkbook wb = new XSSFWorkbook(); + Sheet s = wb.createSheet(); + Row r = s.createRow(0); + r.createCell(0).setCellValue(2.5); + r.createCell(1).setCellValue(1.1); + r.createCell(2).setCellValue(3.2); + r.createCell(4).setCellValue(10.7); + + r = s.createRow(1); + + Cell c1 = r.createCell(0); + c1.setCellFormula("SUM(A1:B1)"); assertEquals(0.0, c1.getNumericCellValue() ); - Cell c2 = r.createCell(1); - c2.setCellFormula("SUM(A1:E1)"); + Cell c2 = r.createCell(1); + c2.setCellFormula("SUM(A1:E1)"); assertEquals(0.0, c2.getNumericCellValue() ); - Cell c3 = r.createCell(2); - c3.setCellFormula("COUNT(A1:A1)"); + Cell c3 = r.createCell(2); + c3.setCellFormula("COUNT(A1:A1)"); assertEquals(0.0, c3.getNumericCellValue() ); - Cell c4 = r.createCell(3); - c4.setCellFormula("COUNTA(A1:E1)"); + Cell c4 = r.createCell(3); + c4.setCellFormula("COUNTA(A1:E1)"); assertEquals(0.0, c4.getNumericCellValue() ); - // Evaluate and test - FormulaEvaluator fe = new XSSFFormulaEvaluator(wb); - - fe.evaluateFormulaCell(c1); - fe.evaluateFormulaCell(c2); - fe.evaluateFormulaCell(c3); - fe.evaluateFormulaCell(c4); - - assertEquals(3.6, c1.getNumericCellValue(), 0.0001); - assertEquals(17.5, c2.getNumericCellValue(), 0.0001); - assertEquals(1, c3.getNumericCellValue(), 0.0001); - assertEquals(4, c4.getNumericCellValue(), 0.0001); - } + // Evaluate and test + FormulaEvaluator fe = new XSSFFormulaEvaluator(wb); + + fe.evaluateFormulaCell(c1); + fe.evaluateFormulaCell(c2); + fe.evaluateFormulaCell(c3); + fe.evaluateFormulaCell(c4); + + assertEquals(3.6, c1.getNumericCellValue(), 0.0001); + assertEquals(17.5, c2.getNumericCellValue(), 0.0001); + assertEquals(1, c3.getNumericCellValue(), 0.0001); + assertEquals(4, c4.getNumericCellValue(), 0.0001); + } + + public void testSharedFormulas(){ + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("shared_formulas.xlsx"); + + XSSFSheet sheet = wb.getSheetAt(0); + + FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); + XSSFCell cell; + + cell = sheet.getRow(1).getCell(0); + assertEquals("B2", cell.getCellFormula()); + assertEquals("ProductionOrderConfirmation", evaluator.evaluate(cell).getStringValue()); + + cell = sheet.getRow(2).getCell(0); + assertEquals("B3", cell.getCellFormula()); + assertEquals("RequiredAcceptanceDate", evaluator.evaluate(cell).getStringValue()); + + cell = sheet.getRow(3).getCell(0); + assertEquals("B4", cell.getCellFormula()); + assertEquals("Header", evaluator.evaluate(cell).getStringValue()); + + cell = sheet.getRow(4).getCell(0); + assertEquals("B5", cell.getCellFormula()); + assertEquals("UniqueDocumentNumberID", evaluator.evaluate(cell).getStringValue()); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFName.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFName.java index 5cf0990d4c..4d273ea26c 100755 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFName.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFName.java @@ -109,4 +109,53 @@ public class TestXSSFName extends TestCase { wb.removeName(0); assertEquals(1, wb.getNumberOfNames()); } + + public void testScope() { + XSSFWorkbook wb = new XSSFWorkbook(); + wb.createSheet(); + wb.createSheet(); + + XSSFName name; + + name = wb.createName(); + name.setNameName("aaa"); + name = wb.createName(); + try { + name.setNameName("aaa"); + fail("Expected exception"); + } catch(Exception e){ + assertEquals("The workbook already contains this name: aaa", e.getMessage()); + } + + name = wb.createName(); + name.setSheetIndex(0); + name.setNameName("aaa"); + name = wb.createName(); + name.setSheetIndex(0); + try { + name.setNameName("aaa"); + fail("Expected exception"); + } catch(Exception e){ + assertEquals("The sheet already contains this name: aaa", e.getMessage()); + } + + name = wb.createName(); + name.setSheetIndex(1); + name.setNameName("aaa"); + name = wb.createName(); + name.setSheetIndex(1); + try { + name.setNameName("aaa"); + fail("Expected exception"); + } catch(Exception e){ + assertEquals("The sheet already contains this name: aaa", e.getMessage()); + } + + int cnt = 0; + for (int i = 0; i < wb.getNumberOfNames(); i++) { + if("aaa".equals(wb.getNameAt(i).getNameName())) cnt++; + } + assertEquals(3, cnt); + } + } diff --git a/src/testcases/org/apache/poi/hssf/data/shared_formulas.xlsx b/src/testcases/org/apache/poi/hssf/data/shared_formulas.xlsx new file mode 100755 index 0000000000000000000000000000000000000000..0a3cb70cb4442c6a1c7a8a93d0bf2e59ff41e588 GIT binary patch literal 10137 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 literal 0 HcmV?d00001 diff --git a/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java b/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java index 755d7cb05f..3960548341 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java @@ -24,12 +24,10 @@ import junit.framework.TestCase; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.RefPtg; -import org.apache.poi.hssf.usermodel.HSSFCell; -import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.hssf.usermodel.RecordInspector; +import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.formula.FormulaParser; +import org.apache.poi.ss.formula.FormulaRenderer; import org.apache.poi.util.LittleEndianInput; /** @@ -62,7 +60,7 @@ public final class TestSharedFormulaRecord extends TestCase { 0x13, 0x42, 0x02, (byte)0xE4, 0x00, }; - + /** * The method SharedFormulaRecord.convertSharedFormulas() converts formulas from * 'shared formula' to 'single cell formula' format. It is important that token operand @@ -70,19 +68,19 @@ public final class TestSharedFormulaRecord extends TestCase { * incorrect encoding. The formula here is one such example (Excel displays #VALUE!). */ public void testConvertSharedFormulasOperandClasses_bug45123() { - + LittleEndianInput in = TestcaseRecordInputStream.createLittleEndian(SHARED_FORMULA_WITH_REF_ARRAYS_DATA); int encodedLen = in.readUShort(); Ptg[] sharedFormula = Ptg.readTokens(encodedLen, in); - + Ptg[] convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 100, 200); - + RefPtg refPtg = (RefPtg) convertedFormula[1]; assertEquals("$C101", refPtg.toFormulaString()); if (refPtg.getPtgClass() == Ptg.CLASS_REF) { throw new AssertionFailedError("Identified bug 45123"); } - + confirmOperandClasses(sharedFormula, convertedFormula); } @@ -97,8 +95,43 @@ public final class TestSharedFormulaRecord extends TestCase { } } } - - /** + + public void testConvertSharedFormulas() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFEvaluationWorkbook fpb = HSSFEvaluationWorkbook.create(wb); + Ptg[] sharedFormula, convertedFormula; + + sharedFormula = FormulaParser.parse("A2", fpb); + convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 0, 0); + confirmOperandClasses(sharedFormula, convertedFormula); + //conversion relative to [0,0] should return the original formula + assertEquals("A2", FormulaRenderer.toFormulaString(fpb, convertedFormula)); + + convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 1, 0); + confirmOperandClasses(sharedFormula, convertedFormula); + //one row down + assertEquals("A3", FormulaRenderer.toFormulaString(fpb, convertedFormula)); + + convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 1, 1); + confirmOperandClasses(sharedFormula, convertedFormula); + //one row down and one cell right + assertEquals("B3", FormulaRenderer.toFormulaString(fpb, convertedFormula)); + + sharedFormula = FormulaParser.parse("SUM(A1:C1)", fpb); + convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 0, 0); + confirmOperandClasses(sharedFormula, convertedFormula); + assertEquals("SUM(A1:C1)", FormulaRenderer.toFormulaString(fpb, convertedFormula)); + + convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 1, 0); + confirmOperandClasses(sharedFormula, convertedFormula); + assertEquals("SUM(A2:C2)", FormulaRenderer.toFormulaString(fpb, convertedFormula)); + + convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 1, 1); + confirmOperandClasses(sharedFormula, convertedFormula); + assertEquals("SUM(B2:D2)", FormulaRenderer.toFormulaString(fpb, convertedFormula)); + } + + /** * Make sure that POI preserves {@link SharedFormulaRecord}s */ public void testPreserveOnReserialize() { diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java b/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java index 70ae5e9999..4ad6b57932 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java @@ -549,4 +549,55 @@ public final class TestNamedRange extends TestCase { } } + + public void testScope() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh1 = wb.createSheet(); + HSSFSheet sh2 = wb.createSheet(); + + HSSFName name; + + name = wb.createName(); + name.setNameName("aaa"); + name = wb.createName(); + try { + name.setNameName("aaa"); + fail("Expected exception"); + } catch(Exception e){ + assertEquals("The workbook already contains this name: aaa", e.getMessage()); + name.setNameName("aaa-2"); + } + + name = wb.createName(); + name.setSheetIndex(0); + name.setNameName("aaa"); + name = wb.createName(); + name.setSheetIndex(0); + try { + name.setNameName("aaa"); + fail("Expected exception"); + } catch(Exception e){ + assertEquals("The sheet already contains this name: aaa", e.getMessage()); + name.setNameName("aaa-2"); + } + + name = wb.createName(); + name.setSheetIndex(1); + name.setNameName("aaa"); + name = wb.createName(); + name.setSheetIndex(1); + try { + name.setNameName("aaa"); + fail("Expected exception"); + } catch(Exception e){ + assertEquals("The sheet already contains this name: aaa", e.getMessage()); + name.setNameName("aaa-2"); + } + + int cnt = 0; + for (int i = 0; i < wb.getNumberOfNames(); i++) { + if("aaa".equals(wb.getNameName(i))) cnt++; + } + assertEquals(3, cnt); + } } -- 2.39.5