]> source.dussan.org Git - poi.git/commitdiff
support removing hyperlink from one cell when hyperlink is shared by many cells
authorPJ Fanning <fanningpj@apache.org>
Wed, 11 Aug 2021 21:13:45 +0000 (21:13 +0000)
committerPJ Fanning <fanningpj@apache.org>
Wed, 11 Aug 2021 21:13:45 +0000 (21:13 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1892246 13f79535-47bb-0310-9956-ffa450edef68

poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java

index 41a434ae43d8d7d1296ead63c3edefb599d73b30..ce883fb8e288f40c40edfe5252419c6416ea5919 100644 (file)
@@ -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<XSSFHyperlink> 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);
             }
         }
     }
index 483336aa797a22b759f9d4dbc1b3e666c6115e6b..d278785d576e571326faa9bc5b999c0a249e0fd0 100644 (file)
@@ -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?");
+                }
+            }
+        }
+    }
+
 }