From: PJ Fanning Date: Wed, 11 Aug 2021 21:13:45 +0000 (+0000) Subject: support removing hyperlink from one cell when hyperlink is shared by many cells X-Git-Tag: REL_5_1_0~42 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=4bac6db36b440ae273d3dab675d8088377b24172;p=poi.git support removing hyperlink from one cell when hyperlink is shared by many cells git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1892246 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 41a434ae43..ce883fb8e2 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -3387,15 +3387,56 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { */ @Internal public void removeHyperlink(int row, int column) { - // CTHyperlinks is regenerated from scratch when writing out the spreadsheet - // so don't worry about maintaining hyperlinks and CTHyperlinks in parallel. - // only maintain hyperlinks - String ref = new CellReference(row, column).formatAsString(); - for (Iterator it = hyperlinks.iterator(); it.hasNext();) { - XSSFHyperlink hyperlink = it.next(); - if (hyperlink.getCellRef().equals(ref)) { - it.remove(); - return; + XSSFHyperlink hyperlink = getHyperlink(row, column); + if (hyperlink != null) { + if (hyperlink.getFirstRow() == row && hyperlink.getLastRow() == row + && hyperlink.getFirstColumn() == column && hyperlink.getLastColumn() == column) { + removeHyperlink(hyperlink); + } else { + //we have a cellRef that spans multiple cells - we just want to remove the hyperlink from one cell + //we delete this hyperlink but add new hyperlinks to cover the other cells that were served + //by the old hyperlink + boolean leftCreated = false; + boolean rightCreated = false; + if (hyperlink.getFirstColumn() < column) { + XSSFHyperlink newLink = new XSSFHyperlink(hyperlink); + newLink.setFirstColumn(hyperlink.getFirstColumn()); + newLink.setLastColumn(column - 1); + newLink.setFirstRow(hyperlink.getFirstRow()); + newLink.setLastRow(hyperlink.getLastRow()); + addHyperlink(newLink); + leftCreated = true; + } + if (hyperlink.getLastColumn() > column) { + XSSFHyperlink newLink = new XSSFHyperlink(hyperlink); + newLink.setFirstColumn(column + 1); + newLink.setLastColumn(hyperlink.getLastColumn()); + newLink.setFirstRow(hyperlink.getFirstRow()); + newLink.setLastRow(hyperlink.getLastRow()); + addHyperlink(newLink); + rightCreated = true; + } + if (hyperlink.getFirstRow() < row) { + XSSFHyperlink newLink = new XSSFHyperlink(hyperlink); + int firstColumn = leftCreated ? row : hyperlink.getFirstColumn(); + int lastColumn = rightCreated ? row : hyperlink.getLastColumn(); + newLink.setFirstColumn(firstColumn); + newLink.setLastColumn(lastColumn); + newLink.setFirstRow(hyperlink.getFirstRow()); + newLink.setLastRow(row - 1); + addHyperlink(newLink); + } + if (hyperlink.getLastRow() > row) { + XSSFHyperlink newLink = new XSSFHyperlink(hyperlink); + int firstColumn = leftCreated ? row : hyperlink.getFirstColumn(); + int lastColumn = rightCreated ? row : hyperlink.getLastColumn(); + newLink.setFirstColumn(firstColumn); + newLink.setLastColumn(lastColumn); + newLink.setFirstRow(row + 1); + newLink.setLastRow(hyperlink.getLastRow()); + addHyperlink(newLink); + } + removeHyperlink(hyperlink); } } } diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java index 483336aa79..d278785d57 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java @@ -22,7 +22,9 @@ import org.apache.poi.hssf.usermodel.HSSFHyperlink; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellAddress; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.XSSFITestDataProvider; @@ -395,7 +397,7 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink { } @Test - void testChangeReference() throws IOException { + void testChangeReference() { XSSFHyperlink hyperlink = new XSSFHyperlink(HyperlinkType.URL); hyperlink.setCellReference("B2"); assertEquals(1, hyperlink.getFirstRow()); @@ -436,7 +438,7 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink { } @Test - void testChangeRowsAndColumns() throws IOException { + void testChangeRowsAndColumns() { XSSFHyperlink hyperlink = new XSSFHyperlink(HyperlinkType.URL); hyperlink.setCellReference("B2"); hyperlink.setLastRow(0); @@ -476,4 +478,46 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink { assertEquals(1, hyperlink.getFirstColumn()); assertEquals(2, hyperlink.getLastColumn()); } + + @Test + void testRemoveSharedHyperlinkFromOneCell() throws IOException { + testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("C3")); + testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("A1")); + testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("E5")); + testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("E1")); + testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("A5")); + testRemoveSharedHyperlinkFromOneCell("D3:D5", new CellAddress("D3")); + testRemoveSharedHyperlinkFromOneCell("D3:D5", new CellAddress("D4")); + testRemoveSharedHyperlinkFromOneCell("D3:D5", new CellAddress("D5")); + } + + private void testRemoveSharedHyperlinkFromOneCell(String area, CellAddress cellAddress) throws IOException { + try (XSSFWorkbook wb = new XSSFWorkbook()) { + XSSFSheet sheet = wb.createSheet(); + XSSFHyperlink hyperlink = new XSSFHyperlink(HyperlinkType.URL); + hyperlink.setAddress("https://poi.apache.org"); + hyperlink.setLocation("poi-location"); + hyperlink.setLabel("poi-label"); + hyperlink.setCellReference(area); + sheet.addHyperlink(hyperlink); + AreaReference areaRef = new AreaReference(hyperlink.getCellRef(), SpreadsheetVersion.EXCEL2007); + for (CellReference cellRef : areaRef.getAllReferencedCells()) { + XSSFHyperlink testHyperlink = sheet.getHyperlink(cellRef.getRow(), cellRef.getCol()); + assertEquals(hyperlink, testHyperlink, "cell " + cellRef.formatAsString() + "has hyperlink?"); + } + sheet.removeHyperlink(cellAddress.getRow(), cellAddress.getColumn()); + assertNull(sheet.getHyperlink(cellAddress), "cell " + cellAddress.formatAsString() + "should no longer has a hyperlink"); + for (CellReference cellRef : areaRef.getAllReferencedCells()) { + if (cellRef.formatAsString().equals(cellAddress.formatAsString())) { + //ignore + } else { + XSSFHyperlink testHyperlink = sheet.getHyperlink(cellRef.getRow(), cellRef.getCol()); + assertEquals(hyperlink.getAddress(), testHyperlink.getAddress(), "cell " + cellRef.formatAsString() + "has hyperlink with right address?"); + assertEquals(hyperlink.getLocation(), testHyperlink.getLocation(), "cell " + cellRef.formatAsString() + "has hyperlink with right location?"); + assertEquals(hyperlink.getLabel(), testHyperlink.getLabel(), "cell " + cellRef.formatAsString() + "has hyperlink with right label?"); + } + } + } + } + }