Bug 58746: Fix missing adjustment of formulas when sheet-ordering is changed.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1722410 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dominik Stadler 2015-12-30 20:31:44 +00:00
parent b39f363fa2
commit 8589924b22
4 changed files with 112 additions and 9 deletions

View File

@ -283,18 +283,42 @@ public final class FormulaShifter {
private Ptg adjustPtgDueToSheetMove(Ptg ptg) { private Ptg adjustPtgDueToSheetMove(Ptg ptg) {
Ptg updatedPtg = null;
if(ptg instanceof Ref3DPtg) { if(ptg instanceof Ref3DPtg) {
Ref3DPtg ref = (Ref3DPtg)ptg; Ref3DPtg ref = (Ref3DPtg)ptg;
if(ref.getExternSheetIndex() == _srcSheetIndex){ int oldSheetIndex = ref.getExternSheetIndex();
// we have to handle a few cases here
// 1. sheet is outside moved sheets, no change necessary
if(oldSheetIndex < _srcSheetIndex &&
oldSheetIndex < _dstSheetIndex) {
return null;
}
if(oldSheetIndex > _srcSheetIndex &&
oldSheetIndex > _dstSheetIndex) {
return null;
}
// 2. ptg refers to the moved sheet
if(oldSheetIndex == _srcSheetIndex) {
ref.setExternSheetIndex(_dstSheetIndex); ref.setExternSheetIndex(_dstSheetIndex);
updatedPtg = ref; return ref;
} else if (ref.getExternSheetIndex() == _dstSheetIndex){ }
ref.setExternSheetIndex(_srcSheetIndex);
updatedPtg = ref; // 3. new index is lower than old one => sheets get moved up
if (_dstSheetIndex < _srcSheetIndex) {
ref.setExternSheetIndex(oldSheetIndex+1);
return ref;
}
// 4. new index is higher than old one => sheets get moved down
if (_dstSheetIndex > _srcSheetIndex) {
ref.setExternSheetIndex(oldSheetIndex-1);
return ref;
} }
} }
return updatedPtg;
return null;
} }
private Ptg rowMoveRefPtg(RefPtgBase rptg) { private Ptg rowMoveRefPtg(RefPtgBase rptg) {

View File

@ -205,8 +205,10 @@ public final class TestXSSFReader extends TestCase {
public void test58747() throws Exception { public void test58747() throws Exception {
OPCPackage pkg = XSSFTestDataSamples.openSamplePackage("58747.xlsx"); OPCPackage pkg = XSSFTestDataSamples.openSamplePackage("58747.xlsx");
ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg); ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg);
assertNotNull(strings);
XSSFReader reader = new XSSFReader(pkg); XSSFReader reader = new XSSFReader(pkg);
StylesTable styles = reader.getStylesTable(); StylesTable styles = reader.getStylesTable();
assertNotNull(styles);
XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) reader.getSheetsData(); XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) reader.getSheetsData();
assertEquals(true, iter.hasNext()); assertEquals(true, iter.hasNext());

View File

@ -1193,4 +1193,33 @@ public final class TestHSSFSheet extends BaseTestSheet {
assertNotNull(record); assertNotNull(record);
wb.close(); wb.close();
} }
@Test
public void test58746() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet first = wb.createSheet("first");
first.createRow(0).createCell(0).setCellValue(1);
HSSFSheet second = wb.createSheet("second");
second.createRow(0).createCell(0).setCellValue(2);
HSSFSheet third = wb.createSheet("third");
HSSFRow row = third.createRow(0);
row.createCell(0).setCellFormula("first!A1");
row.createCell(1).setCellFormula("second!A1");
// re-order for sheet "third"
wb.setSheetOrder("third", 0);
// verify results
assertEquals("third", wb.getSheetAt(0).getSheetName());
assertEquals("first", wb.getSheetAt(1).getSheetName());
assertEquals("second", wb.getSheetAt(2).getSheetName());
assertEquals("first!A1", wb.getSheetAt(0).getRow(0).getCell(0).getCellFormula());
assertEquals("second!A1", wb.getSheetAt(0).getRow(0).getCell(1).getCellFormula());
wb.close();
}
} }

View File

@ -17,12 +17,14 @@
package org.apache.poi.ss.formula; package org.apache.poi.ss.formula;
import junit.framework.TestCase;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.ptg.AreaErrPtg; import org.apache.poi.ss.formula.ptg.AreaErrPtg;
import org.apache.poi.ss.formula.ptg.AreaPtg; import org.apache.poi.ss.formula.ptg.AreaPtg;
import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.Ref3DPtg;
import org.apache.poi.ss.util.CellReference;
import junit.framework.TestCase;
/** /**
* Tests for {@link FormulaShifter}. * Tests for {@link FormulaShifter}.
@ -196,4 +198,50 @@ public final class TestFormulaShifter extends TestCase {
private static AreaPtg createAreaPtg(int initialAreaFirstRow, int initialAreaLastRow, boolean firstRowRelative, boolean lastRowRelative) { private static AreaPtg createAreaPtg(int initialAreaFirstRow, int initialAreaLastRow, boolean firstRowRelative, boolean lastRowRelative) {
return new AreaPtg(initialAreaFirstRow, initialAreaLastRow, 2, 5, firstRowRelative, lastRowRelative, false, false); return new AreaPtg(initialAreaFirstRow, initialAreaLastRow, 2, 5, firstRowRelative, lastRowRelative, false, false);
} }
public void testShiftSheet() {
// 4 sheets, move a sheet from pos 2 to pos 0, i.e. current 0 becomes 1, current 1 becomes pos 2
FormulaShifter shifter = FormulaShifter.createForSheetShift(2, 0);
Ptg[] ptgs = new Ptg[] {
new Ref3DPtg(new CellReference("first", 0, 0, true, true), 0),
new Ref3DPtg(new CellReference("second", 0, 0, true, true), 1),
new Ref3DPtg(new CellReference("third", 0, 0, true, true), 2),
new Ref3DPtg(new CellReference("fourth", 0, 0, true, true), 3),
};
shifter.adjustFormula(ptgs, -1);
assertEquals("formula previously pointing to sheet 0 should now point to sheet 1",
1, ((Ref3DPtg)ptgs[0]).getExternSheetIndex());
assertEquals("formula previously pointing to sheet 1 should now point to sheet 2",
2, ((Ref3DPtg)ptgs[1]).getExternSheetIndex());
assertEquals("formula previously pointing to sheet 2 should now point to sheet 0",
0, ((Ref3DPtg)ptgs[2]).getExternSheetIndex());
assertEquals("formula previously pointing to sheet 3 should be unchanged",
3, ((Ref3DPtg)ptgs[3]).getExternSheetIndex());
}
public void testShiftSheet2() {
// 4 sheets, move a sheet from pos 1 to pos 2, i.e. current 2 becomes 1, current 1 becomes pos 2
FormulaShifter shifter = FormulaShifter.createForSheetShift(1, 2);
Ptg[] ptgs = new Ptg[] {
new Ref3DPtg(new CellReference("first", 0, 0, true, true), 0),
new Ref3DPtg(new CellReference("second", 0, 0, true, true), 1),
new Ref3DPtg(new CellReference("third", 0, 0, true, true), 2),
new Ref3DPtg(new CellReference("fourth", 0, 0, true, true), 3),
};
shifter.adjustFormula(ptgs, -1);
assertEquals("formula previously pointing to sheet 0 should be unchanged",
0, ((Ref3DPtg)ptgs[0]).getExternSheetIndex());
assertEquals("formula previously pointing to sheet 1 should now point to sheet 2",
2, ((Ref3DPtg)ptgs[1]).getExternSheetIndex());
assertEquals("formula previously pointing to sheet 2 should now point to sheet 1",
1, ((Ref3DPtg)ptgs[2]).getExternSheetIndex());
assertEquals("formula previously pointing to sheet 3 should be unchanged",
3, ((Ref3DPtg)ptgs[3]).getExternSheetIndex());
}
} }