mirror of https://github.com/apache/poi.git
refactored XSSFSheet.shiftRows to use FormulaShifter, use a common test superclass for both hssf and xssf
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@744750 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7bab3dc426
commit
627105e288
|
@ -127,6 +127,15 @@ public class POIXMLDocumentPart {
|
|||
relations.add(part);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified part in this package.
|
||||
*/
|
||||
public final void removeRelation(POIXMLDocumentPart part){
|
||||
getPackagePart().removeRelationship(part.getPackageRelationship().getId());
|
||||
getPackagePart().getPackage().removePart(part.getPackagePart());
|
||||
relations.remove(part);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent POIXMLDocumentPart. All parts except root have not-null parent.
|
||||
*
|
||||
|
|
|
@ -27,7 +27,10 @@ import org.apache.poi.ss.formula.FormulaType;
|
|||
import org.apache.poi.ss.formula.FormulaRenderer;
|
||||
import org.apache.poi.xssf.model.CalculationChain;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.FormulaShifter;
|
||||
import org.apache.poi.hssf.record.SharedFormulaRecord;
|
||||
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.CTRow;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
|
||||
|
@ -36,6 +39,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
|
|||
* High level representation of a row of a spreadsheet.
|
||||
*/
|
||||
public class XSSFRow implements Row, Comparable<XSSFRow> {
|
||||
private static final POILogger logger = POILogFactory.getLogger(XSSFRow.class);
|
||||
|
||||
private static final String FILE_FORMAT_NAME = "BIFF12";
|
||||
/**
|
||||
|
@ -406,36 +410,47 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
* @param n the number of rows to move
|
||||
*/
|
||||
protected void shift(int n) {
|
||||
XSSFSheet sheet = getSheet();
|
||||
CalculationChain calcChain = sheet.getWorkbook().getCalculationChain();
|
||||
int rownum = getRowNum() + n;
|
||||
CalculationChain calcChain = sheet.getWorkbook().getCalculationChain();
|
||||
int sheetId = (int)sheet.sheet.getSheetId();
|
||||
for(Cell c : this){
|
||||
XSSFCell cell = (XSSFCell)c;
|
||||
|
||||
//remove the reference in the calculation chain
|
||||
if(calcChain != null) calcChain.removeItem((int)sheet.sheet.getSheetId(), cell.getReference());
|
||||
if(calcChain != null) calcChain.removeItem(sheetId, cell.getReference());
|
||||
|
||||
CTCell ctCell = cell.getCTCell();
|
||||
String r = new CellReference(rownum, cell.getColumnIndex()).formatAsString();
|
||||
ctCell.setR(r);
|
||||
|
||||
if(ctCell.isSetF()){
|
||||
CTCellFormula f = ctCell.getF();
|
||||
String fmla = f.getStringValue();
|
||||
if(fmla.length() > 0) {
|
||||
String shiftedFmla = shiftFormula(fmla, n);
|
||||
f.setStringValue(shiftedFmla);
|
||||
}
|
||||
if(f.isSetRef()){ //Range of cells which the formula applies to.
|
||||
String ref = f.getRef();
|
||||
String shiftedRef = shiftFormula(ref, n);
|
||||
f.setRef(shiftedRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
setRowNum(rownum);
|
||||
}
|
||||
|
||||
protected void updateFormulasAfterCellShift(FormulaShifter shifter) {
|
||||
for(Cell c : this){
|
||||
XSSFCell cell = (XSSFCell)c;
|
||||
|
||||
CTCell ctCell = cell.getCTCell();
|
||||
if(ctCell.isSetF()){
|
||||
CTCellFormula f = ctCell.getF();
|
||||
String formula = f.getStringValue();
|
||||
if(formula.length() > 0) {
|
||||
String shiftedFormula = shiftFormula(formula, shifter);
|
||||
if (shiftedFormula != null) {
|
||||
f.setStringValue(shiftedFormula);
|
||||
}
|
||||
}
|
||||
|
||||
if(f.isSetRef()){ //Range of cells which the formula applies to.
|
||||
String ref = f.getRef();
|
||||
String shiftedRef = shiftFormula(ref, shifter);
|
||||
if(shiftedRef != null) f.setRef(shiftedRef);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift a formula by the specified number of rows
|
||||
* <p>
|
||||
|
@ -443,17 +458,21 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
* </p>
|
||||
*
|
||||
* @param formula the formula to shift
|
||||
* @param n the number of rows to shift
|
||||
* @return the shifted formula
|
||||
* @param shifter the FormulaShifter object that operates on the parsed formula tokens
|
||||
* @return the shifted formula if the formula was changed,
|
||||
* <code>null</code> if the formula wasn't modified
|
||||
*/
|
||||
private String shiftFormula(String formula, int n){
|
||||
private String shiftFormula(String formula, FormulaShifter shifter){
|
||||
XSSFSheet sheet = getSheet();
|
||||
XSSFWorkbook wb = sheet.getWorkbook();
|
||||
int sheetIndex = wb.getSheetIndex(sheet);
|
||||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
|
||||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex);
|
||||
Ptg[] fmla = SharedFormulaRecord.convertSharedFormulas(ptgs, n, 0);
|
||||
return FormulaRenderer.toFormulaString(fpb, fmla);
|
||||
String shiftedFmla = null;
|
||||
if (shifter.adjustFormula(ptgs, sheetIndex)) {
|
||||
shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs);
|
||||
}
|
||||
return shiftedFmla;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import javax.xml.namespace.QName;
|
|||
|
||||
import org.apache.poi.hssf.util.PaneInformation;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.FormulaShifter;
|
||||
import org.apache.poi.hssf.record.SharedFormulaRecord;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
|
@ -60,7 +61,7 @@ import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelations
|
|||
* </p>
|
||||
*/
|
||||
public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
||||
private static POILogger logger = POILogFactory.getLogger(XSSFSheet.class);
|
||||
private static final POILogger logger = POILogFactory.getLogger(XSSFSheet.class);
|
||||
|
||||
/**
|
||||
* Column width measured as the number of characters of the maximum digit width of the
|
||||
|
@ -1442,6 +1443,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
|
||||
for (Iterator<Row> it = rowIterator() ; it.hasNext() ; ) {
|
||||
XSSFRow row = (XSSFRow)it.next();
|
||||
int rownum = row.getRowNum();
|
||||
|
||||
if (!copyRowHeight) {
|
||||
row.setHeight((short)-1);
|
||||
|
@ -1456,11 +1458,39 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
else if (row.getRowNum() >= startRow && row.getRowNum() <= endRow) {
|
||||
row.shift(n);
|
||||
}
|
||||
|
||||
if(sheetComments != null){
|
||||
//TODO shift Note's anchor in the associated /xl/drawing/vmlDrawings#.vml
|
||||
CTCommentList lst = sheetComments.getCTComments().getCommentList();
|
||||
for (CTComment comment : lst.getCommentArray()) {
|
||||
CellReference ref = new CellReference(comment.getRef());
|
||||
if(ref.getRow() == rownum){
|
||||
ref = new CellReference(rownum + n, ref.getCol());
|
||||
comment.setRef(ref.formatAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//rebuild the rows map
|
||||
int sheetIndex = getWorkbook().getSheetIndex(this);
|
||||
FormulaShifter shifter = FormulaShifter.createForRowShift(sheetIndex, startRow, endRow, n);
|
||||
TreeMap<Integer, Row> map = new TreeMap<Integer, Row>();
|
||||
for(Row r : this) map.put(r.getRowNum(), r);
|
||||
for(Row r : this) {
|
||||
XSSFRow row = (XSSFRow)r;
|
||||
row.updateFormulasAfterCellShift(shifter);
|
||||
map.put(r.getRowNum(), r);
|
||||
}
|
||||
rows = map;
|
||||
|
||||
//update formulas on other sheets
|
||||
for(XSSFSheet sheet : getWorkbook()) {
|
||||
if (sheet == this) continue;
|
||||
for(Row r : sheet) {
|
||||
XSSFRow row = (XSSFRow)r;
|
||||
row.updateFormulasAfterCellShift(shifter);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1068,12 +1068,22 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
|
|||
workbook.unsetDefinedNames();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveCalculationChain(){
|
||||
if(calcChain != null){
|
||||
int count = calcChain.getCTCalcChain().getCArray().length;
|
||||
if(count == 0){
|
||||
removeRelation(calcChain);
|
||||
calcChain = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void commit() throws IOException {
|
||||
saveNamedRanges();
|
||||
saveCalculationChain();
|
||||
|
||||
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
|
||||
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorkbook.type.getName().getNamespaceURI(), "workbook"));
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import org.apache.poi.ss.usermodel.BaseTestSheetShiftRows;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
|
||||
/**
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestSheetShiftRows extends BaseTestSheetShiftRows {
|
||||
|
||||
@Override
|
||||
protected Workbook openSampleWorkbook(String sampleFileName) {
|
||||
return XSSFTestDataSamples.openSampleWorkbook(sampleFileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Workbook writeOutAndReadBack(Workbook wb) {
|
||||
return XSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Workbook createWorkbook() {
|
||||
return new XSSFWorkbook();
|
||||
}
|
||||
|
||||
public void testShiftRows() {
|
||||
baseTestShiftRows("SimpleMultiCell.xlsx");
|
||||
}
|
||||
|
||||
public void testShiftRow() {
|
||||
baseTestShiftRow();
|
||||
}
|
||||
|
||||
public void testShiftRow0() {
|
||||
baseTestShiftRow0();
|
||||
}
|
||||
|
||||
//TODO support shifting of page breaks
|
||||
public void $testShiftRowBreaks() {
|
||||
baseTestShiftRowBreaks();
|
||||
}
|
||||
|
||||
//TODO support shifting of comments.
|
||||
public void $testShiftWithComments() {
|
||||
baseTestShiftWithComments("comments.xlsx");
|
||||
}
|
||||
|
||||
public void testShiftWithFormulas() {
|
||||
baseTestShiftWithFormulas("ForShifting.xlsx");
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,285 +0,0 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
|
||||
/**
|
||||
* Tests row shifting capabilities (common base class for HSSF and XSSF tests).
|
||||
*
|
||||
*
|
||||
* @author Shawn Laubach (slaubach at apache dot com)
|
||||
* @author Toshiaki Kamoshida (kamoshida.toshiaki at future dot co dot jp)
|
||||
*/
|
||||
public abstract class BaseTestSheetShiftRows extends TestCase {
|
||||
/**
|
||||
* Override to provide HSSF / XSSF specific way for re-serialising a workbook
|
||||
*/
|
||||
protected abstract Workbook writeOutAndReadBack(Workbook wb);
|
||||
/**
|
||||
* Override to provide way of loading HSSF / XSSF sample workbooks
|
||||
* @param sampleFileName without the ".xls" or ".xlsx" suffix
|
||||
*/
|
||||
protected abstract Workbook openSampleWorkbook(String sampleFileName);
|
||||
/**
|
||||
* Override to provide way of creating HSSF / XSSF workbooks
|
||||
*/
|
||||
protected abstract Workbook createWorkbook();
|
||||
|
||||
/**
|
||||
* Tests the shiftRows function. Does three different shifts.
|
||||
* After each shift, writes the workbook to file and reads back to
|
||||
* check. This ensures that if some changes code that breaks
|
||||
* writing or what not, they realize it.
|
||||
*
|
||||
* @author Shawn Laubach (slaubach at apache dot org)
|
||||
*/
|
||||
public final void testShiftRows(){
|
||||
final String sampleName = "SimpleMultiCell";
|
||||
// Read initial file in
|
||||
Workbook wb = openSampleWorkbook(sampleName);
|
||||
Sheet s = wb.getSheetAt( 0 );
|
||||
|
||||
// Shift the second row down 1 and write to temp file
|
||||
s.shiftRows( 1, 1, 1 );
|
||||
|
||||
wb = writeOutAndReadBack(wb);
|
||||
|
||||
// Read from temp file and check the number of cells in each
|
||||
// row (in original file each row was unique)
|
||||
s = wb.getSheetAt( 0 );
|
||||
|
||||
assertEquals(s.getRow(0).getPhysicalNumberOfCells(), 1);
|
||||
confirmEmptyRow(s, 1);
|
||||
assertEquals(s.getRow(2).getPhysicalNumberOfCells(), 2);
|
||||
assertEquals(s.getRow(3).getPhysicalNumberOfCells(), 4);
|
||||
assertEquals(s.getRow(4).getPhysicalNumberOfCells(), 5);
|
||||
|
||||
// Shift rows 1-3 down 3 in the current one. This tests when
|
||||
// 1 row is blank. Write to a another temp file
|
||||
s.shiftRows( 0, 2, 3 );
|
||||
wb = writeOutAndReadBack(wb);
|
||||
|
||||
// Read and ensure things are where they should be
|
||||
s = wb.getSheetAt(0);
|
||||
confirmEmptyRow(s, 0);
|
||||
confirmEmptyRow(s, 1);
|
||||
confirmEmptyRow(s, 2);
|
||||
assertEquals(s.getRow(3).getPhysicalNumberOfCells(), 1);
|
||||
confirmEmptyRow(s, 4);
|
||||
assertEquals(s.getRow(5).getPhysicalNumberOfCells(), 2);
|
||||
|
||||
// Read the first file again
|
||||
wb = openSampleWorkbook(sampleName);
|
||||
s = wb.getSheetAt( 0 );
|
||||
|
||||
// Shift rows 3 and 4 up and write to temp file
|
||||
s.shiftRows( 2, 3, -2 );
|
||||
wb = writeOutAndReadBack(wb);
|
||||
s = wb.getSheetAt( 0 );
|
||||
assertEquals(s.getRow(0).getPhysicalNumberOfCells(), 3);
|
||||
assertEquals(s.getRow(1).getPhysicalNumberOfCells(), 4);
|
||||
confirmEmptyRow(s, 2);
|
||||
confirmEmptyRow(s, 3);
|
||||
assertEquals(s.getRow(4).getPhysicalNumberOfCells(), 5);
|
||||
}
|
||||
private static void confirmEmptyRow(Sheet s, int rowIx) {
|
||||
Row row = s.getRow(rowIx);
|
||||
assertTrue(row == null || row.getPhysicalNumberOfCells() == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when rows are null.
|
||||
*
|
||||
* @author Toshiaki Kamoshida (kamoshida.toshiaki at future dot co dot jp)
|
||||
*/
|
||||
public final void testShiftRow() {
|
||||
Workbook b = createWorkbook();
|
||||
Sheet s = b.createSheet();
|
||||
s.createRow(0).createCell(0).setCellValue("TEST1");
|
||||
s.createRow(3).createCell(0).setCellValue("TEST2");
|
||||
s.shiftRows(0,4,1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when shifting the first row.
|
||||
*
|
||||
* @author Toshiaki Kamoshida (kamoshida.toshiaki at future dot co dot jp)
|
||||
*/
|
||||
public final void testShiftRow0() {
|
||||
Workbook b = createWorkbook();
|
||||
Sheet s = b.createSheet();
|
||||
s.createRow(0).createCell(0).setCellValue("TEST1");
|
||||
s.createRow(3).createCell(0).setCellValue("TEST2");
|
||||
s.shiftRows(0,4,1);
|
||||
}
|
||||
|
||||
/**
|
||||
* When shifting rows, the page breaks should go with it
|
||||
*
|
||||
*/
|
||||
public final void testShiftRowBreaks() {
|
||||
Workbook b = createWorkbook();
|
||||
Sheet s = b.createSheet();
|
||||
Row row = s.createRow(4);
|
||||
row.createCell(0).setCellValue("test");
|
||||
s.setRowBreak(4);
|
||||
|
||||
s.shiftRows(4, 4, 2);
|
||||
assertTrue("Row number 6 should have a pagebreak", s.isRowBroken(6));
|
||||
}
|
||||
|
||||
|
||||
public final void testShiftWithComments() {
|
||||
final String sampleName = "comments";
|
||||
Workbook wb = openSampleWorkbook(sampleName);
|
||||
|
||||
Sheet sheet = wb.getSheet("Sheet1");
|
||||
assertEquals(3, sheet.getLastRowNum());
|
||||
|
||||
// Verify comments are in the position expected
|
||||
assertNotNull(sheet.getCellComment(0,0));
|
||||
assertNull(sheet.getCellComment(1,0));
|
||||
assertNotNull(sheet.getCellComment(2,0));
|
||||
assertNotNull(sheet.getCellComment(3,0));
|
||||
|
||||
String comment1 = sheet.getCellComment(0,0).getString().getString();
|
||||
assertEquals(comment1,"comment top row1 (index0)\n");
|
||||
String comment3 = sheet.getCellComment(2,0).getString().getString();
|
||||
assertEquals(comment3,"comment top row3 (index2)\n");
|
||||
String comment4 = sheet.getCellComment(3,0).getString().getString();
|
||||
assertEquals(comment4,"comment top row4 (index3)\n");
|
||||
|
||||
// Shifting all but first line down to test comments shifting
|
||||
sheet.shiftRows(1, sheet.getLastRowNum(), 1, true, true);
|
||||
|
||||
// Test that comments were shifted as expected
|
||||
assertEquals(4, sheet.getLastRowNum());
|
||||
assertNotNull(sheet.getCellComment(0,0));
|
||||
assertNull(sheet.getCellComment(1,0));
|
||||
assertNull(sheet.getCellComment(2,0));
|
||||
assertNotNull(sheet.getCellComment(3,0));
|
||||
assertNotNull(sheet.getCellComment(4,0));
|
||||
|
||||
String comment1_shifted = sheet.getCellComment(0,0).getString().getString();
|
||||
assertEquals(comment1,comment1_shifted);
|
||||
String comment3_shifted = sheet.getCellComment(3,0).getString().getString();
|
||||
assertEquals(comment3,comment3_shifted);
|
||||
String comment4_shifted = sheet.getCellComment(4,0).getString().getString();
|
||||
assertEquals(comment4,comment4_shifted);
|
||||
|
||||
// Write out and read back in again
|
||||
// Ensure that the changes were persisted
|
||||
wb = writeOutAndReadBack(wb);
|
||||
sheet = wb.getSheet("Sheet1");
|
||||
assertEquals(4, sheet.getLastRowNum());
|
||||
|
||||
// Verify comments are in the position expected after the shift
|
||||
assertNotNull(sheet.getCellComment(0,0));
|
||||
assertNull(sheet.getCellComment(1,0));
|
||||
assertNull(sheet.getCellComment(2,0));
|
||||
assertNotNull(sheet.getCellComment(3,0));
|
||||
assertNotNull(sheet.getCellComment(4,0));
|
||||
|
||||
comment1_shifted = sheet.getCellComment(0,0).getString().getString();
|
||||
assertEquals(comment1,comment1_shifted);
|
||||
comment3_shifted = sheet.getCellComment(3,0).getString().getString();
|
||||
assertEquals(comment3,comment3_shifted);
|
||||
comment4_shifted = sheet.getCellComment(4,0).getString().getString();
|
||||
assertEquals(comment4,comment4_shifted);
|
||||
}
|
||||
|
||||
/**
|
||||
* See bug #34023
|
||||
*/
|
||||
public void testShiftWithFormulas() {
|
||||
String sampleName = "ForShifting";
|
||||
Workbook wb = openSampleWorkbook(sampleName);
|
||||
|
||||
Sheet sheet = wb.getSheet("Sheet1");
|
||||
assertEquals(20, sheet.getLastRowNum());
|
||||
|
||||
confirmRow(sheet, 0, 1, 171, 1, "ROW(D1)", "100+B1", "COUNT(D1:E1)");
|
||||
confirmRow(sheet, 1, 2, 172, 1, "ROW(D2)", "100+B2", "COUNT(D2:E2)");
|
||||
confirmRow(sheet, 2, 3, 173, 1, "ROW(D3)", "100+B3", "COUNT(D3:E3)");
|
||||
|
||||
confirmCell(sheet, 6, 1, 271, "200+B1");
|
||||
confirmCell(sheet, 7, 1, 272, "200+B2");
|
||||
confirmCell(sheet, 8, 1, 273, "200+B3");
|
||||
|
||||
confirmCell(sheet, 14, 0, 0.0, "A12"); // the cell referred to by this formula will be replaced
|
||||
|
||||
// -----------
|
||||
// Row index 1 -> 11 (row "2" -> row "12")
|
||||
sheet.shiftRows(1, 1, 10);
|
||||
|
||||
// Now check what sheet looks like after move
|
||||
|
||||
// no changes on row "1"
|
||||
confirmRow(sheet, 0, 1, 171, 1, "ROW(D1)", "100+B1", "COUNT(D1:E1)");
|
||||
|
||||
// row "2" is now empty
|
||||
assertEquals(0, sheet.getRow(1).getPhysicalNumberOfCells());
|
||||
|
||||
// Row "2" moved to row "12", and the formula has been updated.
|
||||
// note however that the cached formula result (2) has not been updated. (POI differs from Excel here)
|
||||
confirmRow(sheet, 11, 2, 172, 1, "ROW(D12)", "100+B12", "COUNT(D12:E12)");
|
||||
|
||||
// no changes on row "3"
|
||||
confirmRow(sheet, 2, 3, 173, 1, "ROW(D3)", "100+B3", "COUNT(D3:E3)");
|
||||
|
||||
|
||||
confirmCell(sheet, 14, 0, 0.0, "#REF!");
|
||||
|
||||
|
||||
// Formulas on rows that weren't shifted:
|
||||
confirmCell(sheet, 6, 1, 271, "200+B1");
|
||||
confirmCell(sheet, 7, 1, 272, "200+B12"); // this one moved
|
||||
confirmCell(sheet, 8, 1, 273, "200+B3");
|
||||
|
||||
// check formulas on other sheets
|
||||
Sheet sheet2 = wb.getSheet("Sheet2");
|
||||
confirmCell(sheet2, 0, 0, 371, "300+Sheet1!B1");
|
||||
confirmCell(sheet2, 1, 0, 372, "300+Sheet1!B12");
|
||||
confirmCell(sheet2, 2, 0, 373, "300+Sheet1!B3");
|
||||
|
||||
confirmCell(sheet2, 11, 0, 300, "300+Sheet1!#REF!");
|
||||
|
||||
|
||||
// Note - named ranges formulas have not been updated
|
||||
}
|
||||
|
||||
private static void confirmRow(Sheet sheet, int rowIx, double valA, double valB, double valC,
|
||||
String formulaA, String formulaB, String formulaC) {
|
||||
confirmCell(sheet, rowIx, 4, valA, formulaA);
|
||||
confirmCell(sheet, rowIx, 5, valB, formulaB);
|
||||
confirmCell(sheet, rowIx, 6, valC, formulaC);
|
||||
}
|
||||
|
||||
private static void confirmCell(Sheet sheet, int rowIx, int colIx,
|
||||
double expectedValue, String expectedFormula) {
|
||||
Cell cell = sheet.getRow(rowIx).getCell(colIx);
|
||||
assertEquals(expectedValue, cell.getNumericCellValue(), 0.0);
|
||||
assertEquals(expectedFormula, cell.getCellFormula());
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ package org.apache.poi.hssf.usermodel;
|
|||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.BaseTestSheetShiftRows;
|
||||
|
||||
/**
|
||||
* Tests row shifting capabilities.
|
||||
|
@ -31,7 +32,7 @@ public final class TestSheetShiftRows extends BaseTestSheetShiftRows {
|
|||
|
||||
@Override
|
||||
protected Workbook openSampleWorkbook(String sampleFileName) {
|
||||
return HSSFTestDataSamples.openSampleWorkbook(sampleFileName + ".xls");
|
||||
return HSSFTestDataSamples.openSampleWorkbook(sampleFileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,4 +47,29 @@ public final class TestSheetShiftRows extends BaseTestSheetShiftRows {
|
|||
protected Workbook createWorkbook() {
|
||||
return new HSSFWorkbook();
|
||||
}
|
||||
|
||||
public void testShiftRows() {
|
||||
baseTestShiftRows("SimpleMultiCell.xls");
|
||||
}
|
||||
|
||||
public void testShiftRow() {
|
||||
baseTestShiftRow();
|
||||
}
|
||||
|
||||
public void testShiftRow0() {
|
||||
baseTestShiftRow0();
|
||||
}
|
||||
|
||||
public void testShiftRowBreaks() {
|
||||
baseTestShiftRowBreaks();
|
||||
}
|
||||
|
||||
public void testShiftWithComments() {
|
||||
baseTestShiftWithComments("comments.xls");
|
||||
}
|
||||
|
||||
public void testShiftWithFormulas() {
|
||||
baseTestShiftWithFormulas("ForShifting.xls");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests row shifting capabilities.
|
||||
*
|
||||
* @author Shawn Laubach (slaubach at apache dot com)
|
||||
* @author Toshiaki Kamoshida (kamoshida.toshiaki at future dot co dot jp)
|
||||
*/
|
||||
public abstract class BaseTestSheetShiftRows extends TestCase {
|
||||
/**
|
||||
* Override to provide HSSF / XSSF specific way for re-serialising a workbook
|
||||
*/
|
||||
protected abstract Workbook writeOutAndReadBack(Workbook wb);
|
||||
/**
|
||||
* Override to provide way of loading HSSF / XSSF sample workbooks
|
||||
* @param sampleFileName without the ".xls" or ".xlsx" suffix
|
||||
*/
|
||||
protected abstract Workbook openSampleWorkbook(String sampleFileName);
|
||||
/**
|
||||
* Override to provide way of creating HSSF / XSSF workbooks
|
||||
*/
|
||||
protected abstract Workbook createWorkbook();
|
||||
|
||||
/**
|
||||
* Tests the shiftRows function. Does three different shifts.
|
||||
* After each shift, writes the workbook to file and reads back to
|
||||
* check. This ensures that if some changes code that breaks
|
||||
* writing or what not, they realize it.
|
||||
*
|
||||
* @author Shawn Laubach (slaubach at apache dot org)
|
||||
*/
|
||||
public final void baseTestShiftRows(String sampleName){
|
||||
// Read initial file in
|
||||
Workbook wb = openSampleWorkbook(sampleName);
|
||||
Sheet s = wb.getSheetAt( 0 );
|
||||
|
||||
// Shift the second row down 1 and write to temp file
|
||||
s.shiftRows( 1, 1, 1 );
|
||||
|
||||
wb = writeOutAndReadBack(wb);
|
||||
|
||||
// Read from temp file and check the number of cells in each
|
||||
// row (in original file each row was unique)
|
||||
s = wb.getSheetAt( 0 );
|
||||
|
||||
assertEquals(s.getRow(0).getPhysicalNumberOfCells(), 1);
|
||||
confirmEmptyRow(s, 1);
|
||||
assertEquals(s.getRow(2).getPhysicalNumberOfCells(), 2);
|
||||
assertEquals(s.getRow(3).getPhysicalNumberOfCells(), 4);
|
||||
assertEquals(s.getRow(4).getPhysicalNumberOfCells(), 5);
|
||||
|
||||
// Shift rows 1-3 down 3 in the current one. This tests when
|
||||
// 1 row is blank. Write to a another temp file
|
||||
s.shiftRows( 0, 2, 3 );
|
||||
wb = writeOutAndReadBack(wb);
|
||||
|
||||
// Read and ensure things are where they should be
|
||||
s = wb.getSheetAt(0);
|
||||
confirmEmptyRow(s, 0);
|
||||
confirmEmptyRow(s, 1);
|
||||
confirmEmptyRow(s, 2);
|
||||
assertEquals(s.getRow(3).getPhysicalNumberOfCells(), 1);
|
||||
confirmEmptyRow(s, 4);
|
||||
assertEquals(s.getRow(5).getPhysicalNumberOfCells(), 2);
|
||||
|
||||
// Read the first file again
|
||||
wb = openSampleWorkbook(sampleName);
|
||||
s = wb.getSheetAt( 0 );
|
||||
|
||||
// Shift rows 3 and 4 up and write to temp file
|
||||
s.shiftRows( 2, 3, -2 );
|
||||
wb = writeOutAndReadBack(wb);
|
||||
s = wb.getSheetAt( 0 );
|
||||
assertEquals(s.getRow(0).getPhysicalNumberOfCells(), 3);
|
||||
assertEquals(s.getRow(1).getPhysicalNumberOfCells(), 4);
|
||||
confirmEmptyRow(s, 2);
|
||||
confirmEmptyRow(s, 3);
|
||||
assertEquals(s.getRow(4).getPhysicalNumberOfCells(), 5);
|
||||
}
|
||||
private static void confirmEmptyRow(Sheet s, int rowIx) {
|
||||
Row row = s.getRow(rowIx);
|
||||
assertTrue(row == null || row.getPhysicalNumberOfCells() == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when rows are null.
|
||||
*
|
||||
* @author Toshiaki Kamoshida (kamoshida.toshiaki at future dot co dot jp)
|
||||
*/
|
||||
public final void baseTestShiftRow() {
|
||||
Workbook b = createWorkbook();
|
||||
Sheet s = b.createSheet();
|
||||
s.createRow(0).createCell(0).setCellValue("TEST1");
|
||||
s.createRow(3).createCell(0).setCellValue("TEST2");
|
||||
s.shiftRows(0,4,1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when shifting the first row.
|
||||
*
|
||||
* @author Toshiaki Kamoshida (kamoshida.toshiaki at future dot co dot jp)
|
||||
*/
|
||||
public final void baseTestShiftRow0() {
|
||||
Workbook b = createWorkbook();
|
||||
Sheet s = b.createSheet();
|
||||
s.createRow(0).createCell(0).setCellValue("TEST1");
|
||||
s.createRow(3).createCell(0).setCellValue("TEST2");
|
||||
s.shiftRows(0,4,1);
|
||||
}
|
||||
|
||||
/**
|
||||
* When shifting rows, the page breaks should go with it
|
||||
*
|
||||
*/
|
||||
public final void baseTestShiftRowBreaks() {
|
||||
Workbook b = createWorkbook();
|
||||
Sheet s = b.createSheet();
|
||||
Row row = s.createRow(4);
|
||||
row.createCell(0).setCellValue("test");
|
||||
s.setRowBreak(4);
|
||||
|
||||
s.shiftRows(4, 4, 2);
|
||||
assertTrue("Row number 6 should have a pagebreak", s.isRowBroken(6));
|
||||
}
|
||||
|
||||
|
||||
public final void baseTestShiftWithComments(String sampleName) {
|
||||
Workbook wb = openSampleWorkbook(sampleName);
|
||||
|
||||
Sheet sheet = wb.getSheet("Sheet1");
|
||||
assertEquals(3, sheet.getLastRowNum());
|
||||
|
||||
// Verify comments are in the position expected
|
||||
assertNotNull(sheet.getCellComment(0,0));
|
||||
assertNull(sheet.getCellComment(1,0));
|
||||
assertNotNull(sheet.getCellComment(2,0));
|
||||
assertNotNull(sheet.getCellComment(3,0));
|
||||
|
||||
String comment1 = sheet.getCellComment(0,0).getString().getString();
|
||||
assertEquals(comment1,"comment top row1 (index0)\n");
|
||||
String comment3 = sheet.getCellComment(2,0).getString().getString();
|
||||
assertEquals(comment3,"comment top row3 (index2)\n");
|
||||
String comment4 = sheet.getCellComment(3,0).getString().getString();
|
||||
assertEquals(comment4,"comment top row4 (index3)\n");
|
||||
|
||||
// Shifting all but first line down to test comments shifting
|
||||
sheet.shiftRows(1, sheet.getLastRowNum(), 1, true, true);
|
||||
|
||||
// Test that comments were shifted as expected
|
||||
assertEquals(4, sheet.getLastRowNum());
|
||||
assertNotNull(sheet.getCellComment(0,0));
|
||||
assertNull(sheet.getCellComment(1,0));
|
||||
assertNull(sheet.getCellComment(2,0));
|
||||
assertNotNull(sheet.getCellComment(3,0));
|
||||
assertNotNull(sheet.getCellComment(4,0));
|
||||
|
||||
String comment1_shifted = sheet.getCellComment(0,0).getString().getString();
|
||||
assertEquals(comment1,comment1_shifted);
|
||||
String comment3_shifted = sheet.getCellComment(3,0).getString().getString();
|
||||
assertEquals(comment3,comment3_shifted);
|
||||
String comment4_shifted = sheet.getCellComment(4,0).getString().getString();
|
||||
assertEquals(comment4,comment4_shifted);
|
||||
|
||||
// Write out and read back in again
|
||||
// Ensure that the changes were persisted
|
||||
wb = writeOutAndReadBack(wb);
|
||||
sheet = wb.getSheet("Sheet1");
|
||||
assertEquals(4, sheet.getLastRowNum());
|
||||
|
||||
// Verify comments are in the position expected after the shift
|
||||
assertNotNull(sheet.getCellComment(0,0));
|
||||
assertNull(sheet.getCellComment(1,0));
|
||||
assertNull(sheet.getCellComment(2,0));
|
||||
assertNotNull(sheet.getCellComment(3,0));
|
||||
assertNotNull(sheet.getCellComment(4,0));
|
||||
|
||||
comment1_shifted = sheet.getCellComment(0,0).getString().getString();
|
||||
assertEquals(comment1,comment1_shifted);
|
||||
comment3_shifted = sheet.getCellComment(3,0).getString().getString();
|
||||
assertEquals(comment3,comment3_shifted);
|
||||
comment4_shifted = sheet.getCellComment(4,0).getString().getString();
|
||||
assertEquals(comment4,comment4_shifted);
|
||||
}
|
||||
|
||||
/**
|
||||
* See bug #34023
|
||||
*/
|
||||
public void baseTestShiftWithFormulas(String sampleName) {
|
||||
Workbook wb = openSampleWorkbook(sampleName);
|
||||
|
||||
Sheet sheet = wb.getSheet("Sheet1");
|
||||
assertEquals(20, sheet.getLastRowNum());
|
||||
|
||||
confirmRow(sheet, 0, 1, 171, 1, "ROW(D1)", "100+B1", "COUNT(D1:E1)");
|
||||
confirmRow(sheet, 1, 2, 172, 1, "ROW(D2)", "100+B2", "COUNT(D2:E2)");
|
||||
confirmRow(sheet, 2, 3, 173, 1, "ROW(D3)", "100+B3", "COUNT(D3:E3)");
|
||||
|
||||
confirmCell(sheet, 6, 1, 271, "200+B1");
|
||||
confirmCell(sheet, 7, 1, 272, "200+B2");
|
||||
confirmCell(sheet, 8, 1, 273, "200+B3");
|
||||
|
||||
confirmCell(sheet, 14, 0, 0.0, "A12"); // the cell referred to by this formula will be replaced
|
||||
|
||||
// -----------
|
||||
// Row index 1 -> 11 (row "2" -> row "12")
|
||||
sheet.shiftRows(1, 1, 10);
|
||||
|
||||
// Now check what sheet looks like after move
|
||||
|
||||
// no changes on row "1"
|
||||
confirmRow(sheet, 0, 1, 171, 1, "ROW(D1)", "100+B1", "COUNT(D1:E1)");
|
||||
|
||||
// row "2" is now empty
|
||||
confirmEmptyRow(sheet, 1);
|
||||
|
||||
// Row "2" moved to row "12", and the formula has been updated.
|
||||
// note however that the cached formula result (2) has not been updated. (POI differs from Excel here)
|
||||
confirmRow(sheet, 11, 2, 172, 1, "ROW(D12)", "100+B12", "COUNT(D12:E12)");
|
||||
|
||||
// no changes on row "3"
|
||||
confirmRow(sheet, 2, 3, 173, 1, "ROW(D3)", "100+B3", "COUNT(D3:E3)");
|
||||
|
||||
|
||||
confirmCell(sheet, 14, 0, 0.0, "#REF!");
|
||||
|
||||
|
||||
// Formulas on rows that weren't shifted:
|
||||
confirmCell(sheet, 6, 1, 271, "200+B1");
|
||||
confirmCell(sheet, 7, 1, 272, "200+B12"); // this one moved
|
||||
confirmCell(sheet, 8, 1, 273, "200+B3");
|
||||
|
||||
// check formulas on other sheets
|
||||
Sheet sheet2 = wb.getSheet("Sheet2");
|
||||
confirmCell(sheet2, 0, 0, 371, "300+Sheet1!B1");
|
||||
confirmCell(sheet2, 1, 0, 372, "300+Sheet1!B12");
|
||||
confirmCell(sheet2, 2, 0, 373, "300+Sheet1!B3");
|
||||
|
||||
confirmCell(sheet2, 11, 0, 300, "300+Sheet1!#REF!");
|
||||
|
||||
|
||||
// Note - named ranges formulas have not been updated
|
||||
}
|
||||
|
||||
private static void confirmRow(Sheet sheet, int rowIx, double valA, double valB, double valC,
|
||||
String formulaA, String formulaB, String formulaC) {
|
||||
confirmCell(sheet, rowIx, 4, valA, formulaA);
|
||||
confirmCell(sheet, rowIx, 5, valB, formulaB);
|
||||
confirmCell(sheet, rowIx, 6, valC, formulaC);
|
||||
}
|
||||
|
||||
private static void confirmCell(Sheet sheet, int rowIx, int colIx,
|
||||
double expectedValue, String expectedFormula) {
|
||||
Cell cell = sheet.getRow(rowIx).getCell(colIx);
|
||||
assertEquals(expectedValue, cell.getNumericCellValue(), 0.0);
|
||||
assertEquals(expectedFormula, cell.getCellFormula());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue