]> source.dussan.org Git - poi.git/commitdiff
add support for reading hyperlinks that have cell refs that are area references ...
authorPJ Fanning <fanningpj@apache.org>
Mon, 9 Aug 2021 21:57:40 +0000 (21:57 +0000)
committerPJ Fanning <fanningpj@apache.org>
Mon, 9 Aug 2021 21:57:40 +0000 (21:57 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1892141 13f79535-47bb-0310-9956-ffa450edef68

poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java
poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java
test-data/spreadsheet/sharedhyperlink.xlsx [new file with mode: 0644]

index 6c5f7920653a61a881c4ea1d2f51b6ed74b122c5..8913859a2f3c263c3b513f8eaf73584451a7b6ac 100644 (file)
@@ -22,7 +22,9 @@ import java.net.URISyntaxException;
 import org.apache.poi.common.usermodel.HyperlinkType;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.usermodel.Hyperlink;
+import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.Internal;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink;
@@ -264,20 +266,32 @@ public class XSSFHyperlink implements Hyperlink {
     public void setCellReference(String ref) {
         _ctHyperlink.setRef(ref);
     }
+
     @Internal
     public void setCellReference(CellReference ref) {
         setCellReference(ref.formatAsString());
     }
 
-    private CellReference buildCellReference() {
+    private CellReference buildFirstCellReference() {
+        return buildCellReference(false);
+    }
+
+    private CellReference buildLastCellReference() {
+        return buildCellReference(true);
+    }
+
+    private CellReference buildCellReference(boolean lastCell) {
         String ref = _ctHyperlink.getRef();
         if (ref == null) {
             ref = "A1";
         }
+        if (ref.contains(":")) {
+            AreaReference area = new AreaReference(ref, SpreadsheetVersion.EXCEL2007);
+            return lastCell ? area.getLastCell() : area.getFirstCell();
+        }
         return new CellReference(ref);
     }
 
-
     /**
      * Return the column of the first cell that contains the hyperlink
      *
@@ -285,7 +299,7 @@ public class XSSFHyperlink implements Hyperlink {
      */
     @Override
     public int getFirstColumn() {
-        return buildCellReference().getCol();
+        return buildFirstCellReference().getCol();
     }
 
 
@@ -296,7 +310,7 @@ public class XSSFHyperlink implements Hyperlink {
      */
     @Override
     public int getLastColumn() {
-        return buildCellReference().getCol();
+        return buildLastCellReference().getCol();
     }
 
     /**
@@ -306,7 +320,7 @@ public class XSSFHyperlink implements Hyperlink {
      */
     @Override
     public int getFirstRow() {
-        return buildCellReference().getRow();
+        return buildFirstCellReference().getRow();
     }
 
 
@@ -317,7 +331,7 @@ public class XSSFHyperlink implements Hyperlink {
      */
     @Override
     public int getLastRow() {
-        return buildCellReference().getRow();
+        return buildLastCellReference().getRow();
     }
 
     /**
@@ -327,18 +341,19 @@ public class XSSFHyperlink implements Hyperlink {
      */
     @Override
     public void setFirstColumn(int col) {
-        setCellReference(new CellReference( getFirstRow(), col ));
+        String firstCellRef = CellReference.convertNumToColString(col) + (getFirstRow() + 1);
+        setCellRange(firstCellRef + ":" + buildLastCellReference().formatAsString());
     }
 
     /**
      * Set the column of the last cell that contains the hyperlink.
-     * For XSSF, a Hyperlink may only reference one cell
      *
      * @param col the 0-based column of the last cell that contains the hyperlink
      */
     @Override
     public void setLastColumn(int col) {
-        setFirstColumn(col);
+        String lastCellRef = CellReference.convertNumToColString(col) + (getLastRow() + 1);
+        setCellRange(buildFirstCellReference().formatAsString() + ":" + lastCellRef);
     }
 
     /**
@@ -348,18 +363,28 @@ public class XSSFHyperlink implements Hyperlink {
      */
     @Override
     public void setFirstRow(int row) {
-        setCellReference(new CellReference( row, getFirstColumn() ));
+        String firstCellRef = CellReference.convertNumToColString(getFirstColumn()) + (row + 1);
+        setCellRange(firstCellRef + ":" + buildLastCellReference().formatAsString());
     }
 
     /**
      * Set the row of the last cell that contains the hyperlink.
-     * For XSSF, a Hyperlink may only reference one cell
      *
      * @param row the 0-based row of the last cell that contains the hyperlink
      */
     @Override
     public void setLastRow(int row) {
-        setFirstRow(row);
+        String lastCellRef = CellReference.convertNumToColString(getLastColumn()) + (row + 1);
+        setCellRange(buildFirstCellReference().formatAsString() + ":" + lastCellRef);
+    }
+
+    private void setCellRange(String range) {
+        AreaReference ref = new AreaReference(range, SpreadsheetVersion.EXCEL2007);
+        if(ref.isSingleCell()) {
+            setCellReference(ref.getFirstCell());
+        } else {
+            setCellReference(ref.formatAsString());
+        }
     }
 
     /**
index 27ad23611efa758c2fa216dcb059b2e7988d0e6d..bf3e7396d3eedca5d934452b49f15e05ee88de1b 100644 (file)
@@ -55,23 +55,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.formula.FormulaShifter;
 import org.apache.poi.ss.formula.SheetNameFormatter;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellCopyPolicy;
-import org.apache.poi.ss.usermodel.CellRange;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.DataValidation;
-import org.apache.poi.ss.usermodel.DataValidationHelper;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.Footer;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Header;
-import org.apache.poi.ss.usermodel.IgnoredErrorType;
-import org.apache.poi.ss.usermodel.Name;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Table;
-import org.apache.poi.ss.usermodel.Workbook;
+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.CellRangeAddress;
@@ -846,9 +830,9 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet  {
      */
     @Override
     public XSSFHyperlink getHyperlink(CellAddress addr) {
-        String ref = addr.formatAsString();
-        for(XSSFHyperlink hyperlink : hyperlinks) {
-            if(hyperlink.getCellRef().equals(ref)) {
+        for (XSSFHyperlink hyperlink : getHyperlinkList()) {
+            if (addr.getRow() >= hyperlink.getFirstRow() && addr.getRow() <= hyperlink.getLastRow()
+                    && addr.getColumn() >= hyperlink.getFirstColumn() && addr.getColumn() <= hyperlink.getLastColumn()) {
                 return hyperlink;
             }
         }
index 203fbba80ce5afeb083803f6401035fd689d3952..e95a07d20d203b69a6a6d9a0ca7517cc1bfe2186 100644 (file)
@@ -51,6 +51,27 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
         }
     }
 
+
+    @Test
+    public void readSharedHyperlink() throws IOException {
+        try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("sharedhyperlink.xlsx")) {
+            XSSFSheet sheet = wb.getSheetAt(0);
+
+            XSSFHyperlink hyperlink3 = sheet.getHyperlink(new CellAddress("A3"));
+            XSSFHyperlink hyperlink4 = sheet.getHyperlink(new CellAddress("A4"));
+            XSSFHyperlink hyperlink5 = sheet.getHyperlink(new CellAddress("A5"));
+            assertNotNull(hyperlink3, "hyperlink found?");
+            assertEquals(hyperlink3, hyperlink4);
+            assertEquals(hyperlink3, hyperlink5);
+
+            assertEquals("A3:A5", hyperlink3.getCellRef());
+            assertEquals(0, hyperlink3.getFirstColumn());
+            assertEquals(0, hyperlink3.getLastColumn());
+            assertEquals(2, hyperlink3.getFirstRow());
+            assertEquals(4, hyperlink3.getLastRow());
+        }
+    }
+
     @Test
     void testCreate() throws Exception {
         XSSFWorkbook workbook = new XSSFWorkbook();
@@ -331,7 +352,7 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
     }
 
     @Test
-    void test() throws IOException {
+    void testCellStyle() throws IOException {
         XSSFWorkbook wb = new XSSFWorkbook();
 
         CreationHelper createHelper = wb.getCreationHelper();
@@ -372,4 +393,47 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
         wb.close();
         wbBack.close();
     }
+
+    @Test
+    void testChangeReference() throws IOException {
+        try (XSSFWorkbook wb = new XSSFWorkbook()) {
+            XSSFHyperlink hyperlink = new XSSFHyperlink(HyperlinkType.URL);
+            hyperlink.setCellReference("B2");
+            assertEquals(1, hyperlink.getFirstRow());
+            assertEquals(1, hyperlink.getLastRow());
+            assertEquals(1, hyperlink.getFirstColumn());
+            assertEquals(1, hyperlink.getLastColumn());
+            hyperlink.setFirstRow(0);
+            assertEquals("B1:B2", hyperlink.getCellRef());
+            assertEquals(0, hyperlink.getFirstRow());
+            assertEquals(1, hyperlink.getLastRow());
+            assertEquals(1, hyperlink.getFirstColumn());
+            assertEquals(1, hyperlink.getLastColumn());
+            hyperlink.setLastRow(2);
+            assertEquals("B1:B3", hyperlink.getCellRef());
+            assertEquals(0, hyperlink.getFirstRow());
+            assertEquals(2, hyperlink.getLastRow());
+            assertEquals(1, hyperlink.getFirstColumn());
+            assertEquals(1, hyperlink.getLastColumn());
+            hyperlink.setFirstColumn(0);
+            assertEquals("A1:B3", hyperlink.getCellRef());
+            assertEquals(0, hyperlink.getFirstRow());
+            assertEquals(2, hyperlink.getLastRow());
+            assertEquals(0, hyperlink.getFirstColumn());
+            assertEquals(1, hyperlink.getLastColumn());
+            hyperlink.setLastColumn(2);
+            assertEquals("A1:C3", hyperlink.getCellRef());
+            assertEquals(0, hyperlink.getFirstRow());
+            assertEquals(2, hyperlink.getLastRow());
+            assertEquals(0, hyperlink.getFirstColumn());
+            assertEquals(2, hyperlink.getLastColumn());
+            hyperlink.setFirstColumn(2);
+            hyperlink.setFirstRow(2);
+            assertEquals("C3", hyperlink.getCellRef());
+            assertEquals(2, hyperlink.getFirstRow());
+            assertEquals(2, hyperlink.getLastRow());
+            assertEquals(2, hyperlink.getFirstColumn());
+            assertEquals(2, hyperlink.getLastColumn());
+        }
+    }
 }
diff --git a/test-data/spreadsheet/sharedhyperlink.xlsx b/test-data/spreadsheet/sharedhyperlink.xlsx
new file mode 100644 (file)
index 0000000..d314997
Binary files /dev/null and b/test-data/spreadsheet/sharedhyperlink.xlsx differ