Bug 64460: Fix invalid moving of merged regions

Also fix and enable two tests ignored previously

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1883037 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dominik Stadler 2020-11-01 09:21:45 +00:00
parent 1bd3ddaa75
commit 232d734941
3 changed files with 70 additions and 67 deletions

View File

@ -103,7 +103,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
* contain text, numbers, dates, and formulas. Cells can also be formatted. * contain text, numbers, dates, and formulas. Cells can also be formatted.
* </p> * </p>
*/ */
@SuppressWarnings("deprecation")
public class XSSFSheet extends POIXMLDocumentPart implements Sheet { public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
private static final POILogger logger = POILogFactory.getLogger(XSSFSheet.class); private static final POILogger logger = POILogFactory.getLogger(XSSFSheet.class);
@ -136,7 +135,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
private Map<Integer, CTCellFormula> sharedFormulas; private Map<Integer, CTCellFormula> sharedFormulas;
private SortedMap<String,XSSFTable> tables; private SortedMap<String,XSSFTable> tables;
private List<CellRangeAddress> arrayFormulas; private List<CellRangeAddress> arrayFormulas;
private XSSFDataValidationHelper dataValidationHelper; private final XSSFDataValidationHelper dataValidationHelper;
/** /**
* Creates new XSSFSheet - called by XSSFWorkbook to create a sheet from scratch. * Creates new XSSFSheet - called by XSSFWorkbook to create a sheet from scratch.
@ -3027,7 +3026,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
FormulaShifter formulaShifter = FormulaShifter.createForColumnShift(this.getWorkbook().getSheetIndex(this), this.getSheetName(), startColumn, endColumn, n, SpreadsheetVersion.EXCEL2007); FormulaShifter formulaShifter = FormulaShifter.createForColumnShift(this.getWorkbook().getSheetIndex(this), this.getSheetName(), startColumn, endColumn, n, SpreadsheetVersion.EXCEL2007);
XSSFColumnShifter columnShifter = new XSSFColumnShifter(this); XSSFColumnShifter columnShifter = new XSSFColumnShifter(this);
columnShifter.shiftColumns(startColumn, endColumn, n); columnShifter.shiftColumns(startColumn, endColumn, n);
columnShifter.shiftMergedRegions(startColumn, startColumn, n); columnShifter.shiftMergedRegions(startColumn, endColumn, n);
columnShifter.updateFormulas(formulaShifter); columnShifter.updateFormulas(formulaShifter);
columnShifter.updateConditionalFormatting(formulaShifter); columnShifter.updateConditionalFormatting(formulaShifter);
columnShifter.updateHyperlinks(formulaShifter); columnShifter.updateHyperlinks(formulaShifter);

View File

@ -22,7 +22,6 @@ import org.apache.poi.ss.util.CellAddress;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
@ -33,23 +32,28 @@ import java.io.OutputStream;
import java.util.Locale; import java.util.Locale;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class TestXSSFSheetShiftRowsAndColumns { public class TestXSSFSheetShiftRowsAndColumns {
final File resultDir=new File("build/custom-reports-test"); private static final File resultDir = new File("build/custom-reports-test");
XSSFWorkbook workbook=null;
XSSFSheet sheet=null; private static final int numRows = 4;
String fileName=null; private static final int numCols = 4;
final int numRows=4;
final int numCols=4; private static final int INSERT_ROW = 1;
final int INSERT_ROW=1; private static final int INSERT_COLUMN = 1;
final int INSERT_COLUMN=1; private static final int FIRST_MERGE_ROW = INSERT_ROW+1;
final int FIRST_MERGE_ROW=INSERT_ROW+1; private static final int LAST_MERGE_ROW = numRows-1;
final int LAST_MERGE_ROW=numRows-1; private static final int FIRST_MERGE_COL = INSERT_COLUMN+1;
final int FIRST_MERGE_COL=INSERT_COLUMN+1; private static final int LAST_MERGE_COL = numCols-1;
final int LAST_MERGE_COL=numCols-1;
private XSSFWorkbook workbook = null;
private XSSFSheet sheet = null;
private String fileName = null;
public TestXSSFSheetShiftRowsAndColumns() { public TestXSSFSheetShiftRowsAndColumns() {
resultDir.mkdirs(); assertTrue("Failed to create directory " + resultDir,
resultDir.exists() || resultDir.mkdirs());
} }
/** /**
@ -57,8 +61,10 @@ public class TestXSSFSheetShiftRowsAndColumns {
* 0 to numCols-1. * 0 to numCols-1.
*/ */
@Before @Before
public void setup() { public void setup() throws IOException {
final String procName="TestXSSFSheetShiftRowsAndColumns.setup"; final String procName = "TestXSSFSheetShiftRowsAndColumns.setup";
fileName = procName+".xlsx";
workbook = new XSSFWorkbook(); workbook = new XSSFWorkbook();
sheet = workbook.createSheet(); sheet = workbook.createSheet();
@ -73,10 +79,11 @@ public class TestXSSFSheetShiftRowsAndColumns {
/* /*
* Add a merge area * Add a merge area
*/ */
final CellRangeAddress range=new CellRangeAddress(FIRST_MERGE_ROW,LAST_MERGE_ROW,FIRST_MERGE_COL,LAST_MERGE_COL); final CellRangeAddress range = new CellRangeAddress(FIRST_MERGE_ROW,LAST_MERGE_ROW,FIRST_MERGE_COL,LAST_MERGE_COL);
sheet.addMergedRegion(range); sheet.addMergedRegion(range);
System.out.println(String.format(Locale.US, "\n%s: mergeArea=%s", procName,range)); System.out.println(String.format(Locale.US, "\n%s: mergeArea=%s", procName,range));
writeFile(procName);
} }
@ -84,31 +91,28 @@ public class TestXSSFSheetShiftRowsAndColumns {
* This method writes the workbook to resultDir/fileName. * This method writes the workbook to resultDir/fileName.
*/ */
@After @After
public void cleanup() { public void cleanup() throws IOException {
final String procName="TestXSSFSheetRemoveTable.cleanup"; final String procName = "TestXSSFSheetRemoveTable.cleanup";
if (workbook == null) { if (workbook == null) {
System.out.println(String.format(Locale.ROOT,"%s: workbook==null",procName)); System.out.println(String.format(Locale.ROOT,"%s: workbook==null",procName));
return; return;
} }
if(fileName==null) { if(fileName == null) {
System.out.println(String.format(Locale.ROOT, "%s: fileName==null",procName)); System.out.println(String.format(Locale.ROOT, "%s: fileName==null",procName));
return; return;
} }
final File file=new File(resultDir,fileName); writeFile(procName);
workbook.close();
}
private void writeFile(String procName) throws IOException {
final File file = new File(resultDir,fileName);
try (OutputStream fileOut = new FileOutputStream(file)) { try (OutputStream fileOut = new FileOutputStream(file)) {
workbook.write(fileOut); workbook.write(fileOut);
System.out.println(String.format(Locale.ROOT, "%s: test file written to %s",procName,file.getAbsolutePath())); System.out.println(String.format(Locale.ROOT, "%s: test file written to %s",procName,file.getAbsolutePath()));
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
try {
workbook.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
} }
@ -117,8 +121,8 @@ public class TestXSSFSheetShiftRowsAndColumns {
*/ */
@Test @Test
public void testNoShift() { public void testNoShift() {
final String procName="testNoShift"; final String procName = "testNoShift";
fileName=procName+".xlsx"; fileName = procName+".xlsx";
testCellAddresses(procName,0,0); testCellAddresses(procName,0,0);
testMergeRegion(procName,0,0); testMergeRegion(procName,0,0);
@ -128,21 +132,20 @@ public class TestXSSFSheetShiftRowsAndColumns {
@Test @Test
public void testShiftOneRowAndTestAddresses() { public void testShiftOneRowAndTestAddresses() {
final String procName="testShiftOneRowAndTestAddresses"; final String procName = "testShiftOneRowAndTestAddresses";
fileName=procName+".xlsx"; fileName = procName+".xlsx";
final int nRowsToShift=1; final int nRowsToShift = 1;
sheet.shiftRows(INSERT_ROW, numRows-1, nRowsToShift); sheet.shiftRows(INSERT_ROW, numRows-1, nRowsToShift);
testCellAddresses(procName,nRowsToShift,0); testCellAddresses(procName,nRowsToShift,0);
System.out.println(String.format(Locale.US, "%s: finished without error", procName)); System.out.println(String.format(Locale.US, "%s: finished without error", procName));
} }
@Ignore("currently fails")
@Test @Test
public void testShiftOneRowAndTestMergeRegion() { public void testShiftOneRowAndTestMergeRegion() {
final String procName="testShiftOneRowAndTestMergeRegion"; final String procName = "testShiftOneRowAndTestMergeRegion";
fileName=procName+".xlsx"; fileName = procName+".xlsx";
final int nRowsToShift=1; final int nRowsToShift = 1;
sheet.shiftRows(INSERT_ROW, numRows-1, nRowsToShift); sheet.shiftRows(INSERT_ROW, numRows-1, nRowsToShift);
testMergeRegion(procName,nRowsToShift,0); testMergeRegion(procName,nRowsToShift,0);
@ -151,24 +154,23 @@ public class TestXSSFSheetShiftRowsAndColumns {
@Test @Test
public void testShiftOneColumnAndTestAddresses() { public void testShiftOneColumnAndTestAddresses() {
final String procName="testShiftOneColumnAndTestAddresses"; final String procName = "testShiftOneColumnAndTestAddresses";
fileName=procName+".xlsx"; fileName = procName+".xlsx";
final int nShift=1; final int nShift = 1;
sheet.shiftColumns(INSERT_COLUMN, numCols-1, nShift); sheet.shiftColumns(INSERT_COLUMN, numCols-1, nShift);
testCellAddresses(procName,0,nShift); testCellAddresses(procName,0,nShift);
System.out.println(String.format(Locale.US, "%s: finished without error", procName)); System.out.println(String.format(Locale.US, "%s: finished without error", procName));
} }
@Ignore("currently fails")
@Test @Test
public void testShiftOneColumnAndTestMergeRegion() { public void testShiftOneColumnAndTestMergeRegion() {
final String procName="testShiftOneColumnAndTestMergeRegion"; final String procName = "testShiftOneColumnAndTestMergeRegion";
fileName=procName+".xlsx"; fileName = procName+".xlsx";
final int nShift=1; final int nShift = 1;
sheet.shiftColumns(INSERT_COLUMN, numCols-1, nShift); sheet.shiftColumns(INSERT_COLUMN, numCols-1, nShift);
testMergeRegion(procName,0,nShift); testMergeRegion(procName,0, nShift);
System.out.println(String.format(Locale.US, "%s: finished without error", procName)); System.out.println(String.format(Locale.US, "%s: finished without error", procName));
} }
@ -176,26 +178,26 @@ public class TestXSSFSheetShiftRowsAndColumns {
* Verify that the cell addresses are consistent * Verify that the cell addresses are consistent
*/ */
private void testCellAddresses(String procName,int nRowsToShift,int nColsToShift) { private void testCellAddresses(String procName,int nRowsToShift,int nColsToShift) {
final int nNumRows=nRowsToShift+this.numCols; final int nNumRows = nRowsToShift+ numCols;
final int nNumCols=nColsToShift+this.numCols; final int nNumCols = nColsToShift+ numCols;
for(int nRow=0;nRow<nNumRows;++nRow) { for(int nRow = 0;nRow<nNumRows;++nRow) {
final XSSFRow row=sheet.getRow(nRow); final XSSFRow row = sheet.getRow(nRow);
if(row==null) { if(row == null) {
System.out.println(String.format(Locale.US, "%s: Row %d is empty", procName,nRow)); System.out.println(String.format(Locale.US, "%s: Row %d is empty", procName,nRow));
continue; continue;
} }
for(int nCol=0;nCol<nNumCols;++nCol) { for(int nCol = 0;nCol<nNumCols;++nCol) {
final String address=new CellAddress(nRow,nCol).formatAsString(); final String address = new CellAddress(nRow,nCol).formatAsString();
final XSSFCell cell=row.getCell(nCol); final XSSFCell cell = row.getCell(nCol);
if(cell==null) { if(cell == null) {
System.out.println(String.format(Locale.US, "%s: Cell %s is empty", procName,address)); System.out.println(String.format(Locale.US, "%s: Cell %s is empty", procName,address));
continue; continue;
} }
final CTCell ctCell=cell.getCTCell(); final CTCell ctCell = cell.getCTCell();
final Object cellAddress=cell.getAddress().formatAsString(); final Object cellAddress = cell.getAddress().formatAsString();
final Object r=ctCell.getR(); final Object r = ctCell.getR();
if(nCol==0 || nRow==0) { if(nCol == 0 || nRow == 0) {
System.out.println(String.format(Locale.US, "%s: Row %d col %d address=%s cell.address=%s cell.getR=%s", procName, nRow, System.out.println(String.format(Locale.US, "%s: Row %d col %d address=%s cell.address=%s cell.getR=%s", procName, nRow,
nCol, address, cellAddress, ctCell.getR())); nCol, address, cellAddress, ctCell.getR()));
} }
@ -210,9 +212,10 @@ public class TestXSSFSheetShiftRowsAndColumns {
* Verify that the merge area is consistent * Verify that the merge area is consistent
*/ */
private void testMergeRegion(String procName,int nRowsToShift,int nColsToShift) { private void testMergeRegion(String procName,int nRowsToShift,int nColsToShift) {
final CellRangeAddress range=sheet.getMergedRegion(0); final CellRangeAddress range = sheet.getMergedRegion(0);
assertEquals(String.format(Locale.US, "%s: Testing merge area %s",procName,range),range, assertEquals(String.format(Locale.US, "%s: Testing merge area %s", procName, range),
new CellRangeAddress(FIRST_MERGE_ROW,LAST_MERGE_ROW+nRowsToShift,FIRST_MERGE_COL,LAST_MERGE_COL+nColsToShift)); new CellRangeAddress(FIRST_MERGE_ROW + nRowsToShift, LAST_MERGE_ROW + nRowsToShift,
FIRST_MERGE_COL + nColsToShift, LAST_MERGE_COL + nColsToShift),
range);
} }
} }

View File

@ -95,6 +95,7 @@ public abstract class BaseTestSheetShiftColumns {
style.setVerticalAlignment(VerticalAlignment.BOTTOM); style.setVerticalAlignment(VerticalAlignment.BOTTOM);
return style; return style;
} }
@Test @Test
public void testShiftOneColumnRight() { public void testShiftOneColumnRight() {
sheet1.shiftColumns(1, 2, 1); sheet1.shiftColumns(1, 2, 1);