diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java index 4b70d50e25..b0c9a92f35 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java @@ -58,44 +58,47 @@ public class XSSFHyperlink implements Hyperlink { _ctHyperlink = ctHyperlink; _externalRel = hyperlinkRel; - // Figure out the Hyperlink type and distination + // Figure out the Hyperlink type and destination - // If it has a location, it's internal - if (ctHyperlink.getLocation() != null) { - _type = Hyperlink.LINK_DOCUMENT; - _location = ctHyperlink.getLocation(); - } else { - // Otherwise it's somehow external, check - // the relation to see how - if (_externalRel == null) { - if (ctHyperlink.getId() != null) { - throw new IllegalStateException("The hyperlink for cell " + ctHyperlink.getRef() + - " references relation " + ctHyperlink.getId() + ", but that didn't exist!"); - } + if (_externalRel == null) { + // If it has a location, it's internal + if (ctHyperlink.getLocation() != null) { + _type = Hyperlink.LINK_DOCUMENT; + _location = ctHyperlink.getLocation(); + } else if (ctHyperlink.getId() != null) { + throw new IllegalStateException("The hyperlink for cell " + + ctHyperlink.getRef() + " references relation " + + ctHyperlink.getId() + ", but that didn't exist!"); + } else { // hyperlink is internal and is not related to other parts _type = Hyperlink.LINK_DOCUMENT; - } else { - URI target = _externalRel.getTargetURI(); - _location = target.toString(); - - // Try to figure out the type - if (_location.startsWith("http://") || _location.startsWith("https://") - || _location.startsWith("ftp://")) { - _type = Hyperlink.LINK_URL; - } else if (_location.startsWith("mailto:")) { - _type = Hyperlink.LINK_EMAIL; - } else { - _type = Hyperlink.LINK_FILE; - } + } + } else { + URI target = _externalRel.getTargetURI(); + _location = target.toString(); + if (ctHyperlink.getLocation() != null) { + // URI fragment + _location += "#" + ctHyperlink.getLocation(); } - + // Try to figure out the type + if (_location.startsWith("http://") || _location.startsWith("https://") + || _location.startsWith("ftp://")) { + _type = Hyperlink.LINK_URL; + } else if (_location.startsWith("mailto:")) { + _type = Hyperlink.LINK_EMAIL; + } else { + _type = Hyperlink.LINK_FILE; + } } - } - + + } + /** * Create a new XSSFHyperlink. This method is for Internal use only. - * XSSFHyperlinks can be created by XSSFCreationHelper. + * XSSFHyperlinks can be created by {@link XSSFCreationHelper}. + * See the spreadsheet quick-guide + * for an example. * * @param other the hyperlink to copy */ @@ -165,7 +168,8 @@ public class XSSFHyperlink implements Hyperlink { } /** - * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file + * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file. + * The is the hyperlink target. * * @return the address of this hyperlink */ @@ -216,6 +220,7 @@ public class XSSFHyperlink implements Hyperlink { /** * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file + * This is the hyperlink target. * * @param address - the address of this hyperlink */ diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java index d5e3df294e..ec68569b73 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java @@ -17,12 +17,12 @@ package org.apache.poi.xssf.usermodel; -import java.io.IOException; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import java.io.IOException; + import org.apache.poi.hssf.usermodel.HSSFHyperlink; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; @@ -31,6 +31,7 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.util.CellAddress; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; @@ -292,4 +293,39 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink { // Are HSSFHyperlink.label and XSSFHyperlink.tooltip the same? If so, perhaps one of these needs renamed for a consistent Hyperlink interface // assertEquals("label", xlink.getTooltip()); } + + /* bug 59775: XSSFHyperlink has wrong type if it contains a location (CTHyperlink#getLocation) + * URLs with a hash mark (#) are still URL hyperlinks, not document links + */ + @Test + public void testURLsWithHashMark() throws IOException { + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("59775.xlsx"); + XSSFSheet sh = wb.getSheetAt(0); + CellAddress A2 = new CellAddress("A2"); + CellAddress A3 = new CellAddress("A3"); + CellAddress A4 = new CellAddress("A4"); + CellAddress A7 = new CellAddress("A7"); + + XSSFHyperlink link = sh.getHyperlink(A2); + assertEquals("address", "A2", link.getCellRef()); + assertEquals("link type", Hyperlink.LINK_URL, link.getType()); + assertEquals("link target", "http://twitter.com/#!/apacheorg", link.getAddress()); + + link = sh.getHyperlink(A3); + assertEquals("address", "A3", link.getCellRef()); + assertEquals("link type", Hyperlink.LINK_URL, link.getType()); + assertEquals("link target", "http://www.bailii.org/databases.html#ie", link.getAddress()); + + link = sh.getHyperlink(A4); + assertEquals("address", "A4", link.getCellRef()); + assertEquals("link type", Hyperlink.LINK_URL, link.getType()); + assertEquals("link target", "https://en.wikipedia.org/wiki/Apache_POI#See_also", link.getAddress()); + + link = sh.getHyperlink(A7); + assertEquals("address", "A7", link.getCellRef()); + assertEquals("link type", Hyperlink.LINK_DOCUMENT, link.getType()); + assertEquals("link target", "Sheet1", link.getAddress()); + + wb.close(); + } } diff --git a/test-data/spreadsheet/59775.xlsx b/test-data/spreadsheet/59775.xlsx new file mode 100644 index 0000000000..03238bd2ab Binary files /dev/null and b/test-data/spreadsheet/59775.xlsx differ