* @param endRow the row to end shifting
* @param n the number of rows to shift
*/
+ @Override
public void shiftRows(int startRow, int endRow, int n) {
shiftRows(startRow, endRow, n, false, false);
}
* @param copyRowHeight whether to copy the row height during the shift
* @param resetOriginalRowHeight whether to set the original row's height to the default
*/
+ @Override
public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
shiftRows(startRow, endRow, n, copyRowHeight, resetOriginalRowHeight, true);
}
public void shiftRows(int startRow, int endRow, int n,
boolean copyRowHeight, boolean resetOriginalRowHeight, boolean moveComments) {
int s, inc;
+ if (endRow < startRow) {
+ throw new IllegalArgumentException("startRow must be less than or equal to endRow. To shift rows up, use n<0.");
+ }
if (n < 0) {
s = startRow;
inc = 1;
return;
}
+ // Shift comments
if (moveComments) {
_sheet.getNoteRecords();
}
+ // Shift Merged Regions
shiftMerged(startRow, endRow, n, true);
+
+ // Shift Row Breaks
_sheet.getPageSettings().shiftRowBreaks(startRow, endRow, n);
+
+ // Delete overwritten hyperlinks
+ final int firstOverwrittenRow = startRow + n;
+ final int lastOverwrittenRow = endRow + n;
+ for (HSSFHyperlink link : getHyperlinkList()) {
+ // If hyperlink is fully contained in the rows that will be overwritten, delete the hyperlink
+ if (firstOverwrittenRow <= link.getFirstRow() &&
+ link.getFirstRow() <= lastOverwrittenRow &&
+ lastOverwrittenRow <= link.getLastRow() &&
+ link.getLastRow() <= lastOverwrittenRow) {
+ removeHyperlink(link);
+ }
+ }
for (int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc) {
HSSFRow row = getRow(rowNum);
// Remove all the old cells from the row we'll
- // be writing too, before we start overwriting
+ // be writing to, before we start overwriting
// any cells. This avoids issues with cells
// changing type, and records not being correctly
// overwritten
// the destination row
for (Iterator<Cell> cells = row.cellIterator(); cells.hasNext(); ) {
HSSFCell cell = (HSSFCell) cells.next();
+ HSSFHyperlink link = cell.getHyperlink();
row.removeCell(cell);
CellValueRecordInterface cellRecord = cell.getCellValueRecord();
cellRecord.setRow(rowNum + n);
row2Replace.createCellFromRecord(cellRecord);
_sheet.addValueRecord(rowNum + n, cellRecord);
- HSSFHyperlink link = cell.getHyperlink();
if (link != null) {
link.setFirstRow(link.getFirstRow() + n);
link.setLastRow(link.getLastRow() + n);
}
return hyperlinkList;
}
+
+ /**
+ * Remove the underlying HyperlinkRecord from this sheet.
+ * If multiple HSSFHyperlinks refer to the same HyperlinkRecord, all HSSFHyperlinks will be removed.
+ *
+ * @param link the HSSFHyperlink wrapper around the HyperlinkRecord to remove
+ */
+ protected void removeHyperlink(HSSFHyperlink link) {
+ removeHyperlink(link.record);
+ }
+
+ /**
+ * Remove the underlying HyperlinkRecord from this sheet
+ *
+ * @param link the underlying HyperlinkRecord to remove from this sheet
+ */
+ protected void removeHyperlink(HyperlinkRecord link) {
+ for (Iterator<RecordBase> it = _sheet.getRecords().iterator(); it.hasNext();) {
+ RecordBase rec = it.next();
+ if (rec instanceof HyperlinkRecord) {
+ HyperlinkRecord recLink = (HyperlinkRecord) rec;
+ if (link == recLink) {
+ it.remove();
+ // if multiple HSSFHyperlinks refer to the same record
+ return;
+ }
+ }
+ }
+ }
public HSSFSheetConditionalFormatting getSheetConditionalFormatting() {
return new HSSFSheetConditionalFormatting(this);
import org.apache.poi.ss.usermodel.BaseTestSheetShiftRows;
import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Comment;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.Hyperlink;
-import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
wb.close();
}
-
- @Test
- public void testBug46742_shiftHyperlinks() throws IOException {
- XSSFWorkbook wb = new XSSFWorkbook();
- Sheet sheet = wb.createSheet("test");
- Row row = sheet.createRow(0);
-
- // How to create hyperlinks
- // https://poi.apache.org/spreadsheet/quick-guide.html#Hyperlinks
- XSSFCreationHelper helper = wb.getCreationHelper();
- CellStyle hlinkStyle = wb.createCellStyle();
- Font hlinkFont = wb.createFont();
- hlinkFont.setUnderline(Font.U_SINGLE);
- hlinkFont.setColor(IndexedColors.BLUE.getIndex());
- hlinkStyle.setFont(hlinkFont);
-
- // 3D relative document link
- Cell cell = row.createCell(0);
- cell.setCellStyle(hlinkStyle);
- createHyperlink(helper, cell, Hyperlink.LINK_DOCUMENT, "test!E1");
-
- // URL
- cell = row.createCell(1);
- cell.setCellStyle(hlinkStyle);
- createHyperlink(helper, cell, Hyperlink.LINK_URL, "http://poi.apache.org/");
-
- // row0 will be shifted on top of row1, so this URL should be removed from the workbook
- Row overwrittenRow = sheet.createRow(3);
- cell = overwrittenRow.createCell(2);
- cell.setCellStyle(hlinkStyle);
- createHyperlink(helper, cell, Hyperlink.LINK_EMAIL, "mailto:poi@apache.org");
-
- // hyperlinks on this row are unaffected by the row shifting, so the hyperlinks should not move
- Row unaffectedRow = sheet.createRow(20);
- cell = unaffectedRow.createCell(3);
- cell.setCellStyle(hlinkStyle);
- createHyperlink(helper, cell, Hyperlink.LINK_FILE, "54524.xlsx");
-
- cell = wb.createSheet("other").createRow(0).createCell(0);
- cell.setCellStyle(hlinkStyle);
- createHyperlink(helper, cell, Hyperlink.LINK_URL, "http://apache.org/");
-
- int startRow = 0;
- int endRow = 0;
- int n = 3;
- sheet.shiftRows(startRow, endRow, n);
-
- XSSFWorkbook read = XSSFTestDataSamples.writeOutAndReadBack(wb);
- wb.close();
-
- XSSFSheet sh = read.getSheet("test");
-
- Row shiftedRow = sh.getRow(3);
-
- // document link anchored on a shifted cell should be moved
- // Note that hyperlinks do not track what they point to, so this hyperlink should still refer to test!E1
- verifyHyperlink(shiftedRow.getCell(0), Hyperlink.LINK_DOCUMENT, "test!E1");
-
- // URL, EMAIL, and FILE links anchored on a shifted cell should be moved
- verifyHyperlink(shiftedRow.getCell(1), Hyperlink.LINK_URL, "http://poi.apache.org/");
-
- // Make sure hyperlinks were moved and not copied
- assertNull(sh.getRow(0));
-
- // Make sure hyperlink in overwritten row is deleted
- assertEquals(3, sh.getHyperlinkList().size());
- for (XSSFHyperlink link : sh.getHyperlinkList()) {
- if ("C4".equals(link.getCellRef())) {
- fail("Row 4, including the hyperlink at C4, should have been deleted when Row 1 was shifted on top of it.");
- }
- }
-
- // Make sure unaffected rows are not shifted
- Cell unaffectedCell = sh.getRow(20).getCell(3);
- assertTrue(cellHasHyperlink(unaffectedCell));
- verifyHyperlink(unaffectedCell, Hyperlink.LINK_FILE, "54524.xlsx");
-
- // Make sure cells on other sheets are not affected
- unaffectedCell = read.getSheet("other").getRow(0).getCell(0);
- assertTrue(cellHasHyperlink(unaffectedCell));
- verifyHyperlink(unaffectedCell, Hyperlink.LINK_URL, "http://apache.org/");
-
- read.close();
- }
-
- private void createHyperlink(CreationHelper helper, Cell cell, int linkType, String ref) {
- cell.setCellValue(ref);
- Hyperlink link = helper.createHyperlink(linkType);
- link.setAddress(ref);
- cell.setHyperlink(link);
- }
-
- private void verifyHyperlink(Cell cell, int linkType, String ref) {
- assertTrue(cellHasHyperlink(cell));
- Hyperlink link = cell.getHyperlink();
- assertEquals(linkType, link.getType());
- assertEquals(ref, link.getAddress());
- }
-
- private boolean cellHasHyperlink(Cell cell) {
- return (cell != null) && (cell.getHyperlink() != null);
- }
}
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.ITestDataProvider;
+import org.apache.poi.ss.util.CellAddress;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.junit.Test;
wb.close();
}
+
+ /**
+ * Unified test for:
+ * bug 46742: XSSFSheet.shiftRows should shift hyperlinks
+ * bug 52903: HSSFSheet.shiftRows should shift hyperlinks
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testBug46742_52903_shiftHyperlinks() throws IOException {
+ Workbook wb = _testDataProvider.createWorkbook();
+ Sheet sheet = wb.createSheet("test");
+ Row row = sheet.createRow(0);
+
+ // How to create hyperlinks
+ // https://poi.apache.org/spreadsheet/quick-guide.html#Hyperlinks
+ CreationHelper helper = wb.getCreationHelper();
+ CellStyle hlinkStyle = wb.createCellStyle();
+ Font hlinkFont = wb.createFont();
+ hlinkFont.setUnderline(Font.U_SINGLE);
+ hlinkFont.setColor(IndexedColors.BLUE.getIndex());
+ hlinkStyle.setFont(hlinkFont);
+
+ // 3D relative document link
+ // CellAddress=A1, shifted to A4
+ Cell cell = row.createCell(0);
+ cell.setCellStyle(hlinkStyle);
+ createHyperlink(helper, cell, Hyperlink.LINK_DOCUMENT, "test!E1");
+
+ // URL
+ cell = row.createCell(1);
+ // CellAddress=B1, shifted to B4
+ cell.setCellStyle(hlinkStyle);
+ createHyperlink(helper, cell, Hyperlink.LINK_URL, "http://poi.apache.org/");
+
+ // row0 will be shifted on top of row1, so this URL should be removed from the workbook
+ Row overwrittenRow = sheet.createRow(3);
+ cell = overwrittenRow.createCell(2);
+ // CellAddress=C4, will be overwritten (deleted)
+ cell.setCellStyle(hlinkStyle);
+ createHyperlink(helper, cell, Hyperlink.LINK_EMAIL, "mailto:poi@apache.org");
+
+ // hyperlinks on this row are unaffected by the row shifting, so the hyperlinks should not move
+ Row unaffectedRow = sheet.createRow(20);
+ cell = unaffectedRow.createCell(3);
+ // CellAddress=D21, will be unaffected
+ cell.setCellStyle(hlinkStyle);
+ createHyperlink(helper, cell, Hyperlink.LINK_FILE, "54524.xlsx");
+
+ cell = wb.createSheet("other").createRow(0).createCell(0);
+ // CellAddress=Other!A1, will be unaffected
+ cell.setCellStyle(hlinkStyle);
+ createHyperlink(helper, cell, Hyperlink.LINK_URL, "http://apache.org/");
+
+ int startRow = 0;
+ int endRow = 0;
+ int n = 3;
+ sheet.shiftRows(startRow, endRow, n);
+
+ Workbook read = _testDataProvider.writeOutAndReadBack(wb);
+ wb.close();
+
+ Sheet sh = read.getSheet("test");
+
+ Row shiftedRow = sh.getRow(3);
+
+ // document link anchored on a shifted cell should be moved
+ // Note that hyperlinks do not track what they point to, so this hyperlink should still refer to test!E1
+ verifyHyperlink(shiftedRow.getCell(0), Hyperlink.LINK_DOCUMENT, "test!E1");
+
+ // URL, EMAIL, and FILE links anchored on a shifted cell should be moved
+ verifyHyperlink(shiftedRow.getCell(1), Hyperlink.LINK_URL, "http://poi.apache.org/");
+
+ // Make sure hyperlinks were moved and not copied
+ assertNull("Document hyperlink should be moved, not copied", sh.getHyperlink(0, 0));
+ assertNull("URL hyperlink should be moved, not copied", sh.getHyperlink(0, 1));
+
+ // Make sure hyperlink in overwritten row is deleted
+ System.out.println(sh.getHyperlinkList());
+ assertEquals(3, sh.getHyperlinkList().size());
+ CellAddress unexpectedLinkAddress = new CellAddress("C4");
+ for (Hyperlink link : sh.getHyperlinkList()) {
+ final CellAddress linkAddress = new CellAddress(link.getFirstRow(), link.getFirstColumn());
+ System.out.println(linkAddress.formatAsString());
+ if (linkAddress.equals(unexpectedLinkAddress)) {
+ fail("Row 4, including the hyperlink at C4, should have " +
+ "been deleted when Row 1 was shifted on top of it.");
+ }
+ }
+
+ // Make sure unaffected rows are not shifted
+ Cell unaffectedCell = sh.getRow(20).getCell(3);
+ assertTrue(cellHasHyperlink(unaffectedCell));
+ verifyHyperlink(unaffectedCell, Hyperlink.LINK_FILE, "54524.xlsx");
+
+ // Make sure cells on other sheets are not affected
+ unaffectedCell = read.getSheet("other").getRow(0).getCell(0);
+ assertTrue(cellHasHyperlink(unaffectedCell));
+ verifyHyperlink(unaffectedCell, Hyperlink.LINK_URL, "http://apache.org/");
+
+ read.close();
+ }
+
+ private void createHyperlink(CreationHelper helper, Cell cell, int linkType, String ref) {
+ cell.setCellValue(ref);
+ Hyperlink link = helper.createHyperlink(linkType);
+ link.setAddress(ref);
+ cell.setHyperlink(link);
+ }
+
+ private void verifyHyperlink(Cell cell, int linkType, String ref) {
+ assertTrue(cellHasHyperlink(cell));
+ Hyperlink link = cell.getHyperlink();
+ assertEquals(linkType, link.getType());
+ assertEquals(ref, link.getAddress());
+ }
+
+ private boolean cellHasHyperlink(Cell cell) {
+ return (cell != null) && (cell.getHyperlink() != null);
+ }
}