diff --git a/build.xml b/build.xml index 2794f6acd2..5dd4a52fbc 100644 --- a/build.xml +++ b/build.xml @@ -151,8 +151,8 @@ under the License. - - + + diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java index 3332dd6ffc..8e93def77f 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -423,14 +423,20 @@ public final class XSSFCell implements Cell { /** * Creates an XSSFRichTextString for you. */ - public RichTextString createRichTextString(String text) { - return new XSSFRichTextString(text); - } - - public Hyperlink getHyperlink() { - return row.getSheet().getHyperlink(row.getRowNum(), cellNum); - } - public void setHyperlink(Hyperlink hyperlink) { - row.getSheet().setCellHyperlink((XSSFHyperlink)hyperlink); - } + public RichTextString createRichTextString(String text) { + return new XSSFRichTextString(text); + } + + public Hyperlink getHyperlink() { + return row.getSheet().getHyperlink(row.getRowNum(), cellNum); + } + public void setHyperlink(Hyperlink hyperlink) { + XSSFHyperlink link = (XSSFHyperlink)hyperlink; + + // Assign to us + link.setCellReference( new CellReference(row.getRowNum(), cellNum).formatAsString() ); + + // Add to the lists + row.getSheet().setCellHyperlink(link); + } } 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 2a27138a75..c937bc99d6 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java @@ -22,7 +22,6 @@ import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.util.CellReference; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink; -import org.openxml4j.opc.Package; import org.openxml4j.opc.PackagePart; import org.openxml4j.opc.PackageRelationship; @@ -46,7 +45,7 @@ public class XSSFHyperlink implements Hyperlink { this.ctHyperlink = ctHyperlink; this.externalRel = hyperlinkRel; - // Figure out the Hyperlink type + // Figure out the Hyperlink type and distination // If it has a location, it's internal if(ctHyperlink.getLocation() != null) { @@ -62,10 +61,19 @@ public class XSSFHyperlink implements Hyperlink { throw new IllegalStateException("A sheet hyperlink must either have a location, or a relationship. Found:\n" + ctHyperlink); } } - // TODO - //URI target = externalRel.getTargetURI(); - //location = target.toString(); + 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; + } } } @@ -89,7 +97,12 @@ public class XSSFHyperlink implements Hyperlink { */ protected void generateRelationIfNeeded(PackagePart sheetPart) { if(needsRelationToo()) { - // TODO + // Generate the relation + PackageRelationship rel = + sheetPart.addExternalRelationship(location, XSSFWorkbook.SHEET_HYPERLINKS.getRelation()); + + // Update the r:id + ctHyperlink.setId(rel.getId()); } } @@ -119,6 +132,13 @@ public class XSSFHyperlink implements Hyperlink { location = address; } + /** + * Assigns this hyperlink to the given cell reference + */ + protected void setCellReference(String ref) { + ctHyperlink.setRef(ref); + } + private CellReference buildCellReference() { return new CellReference(ctHyperlink.getRef()); } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 5bffc981aa..1976e79b87 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -180,10 +180,9 @@ public class XSSFSheet implements Sheet { hyperRel = hyperRels.getRelationshipByID(hyperlink.getId()); } - // TODO: fix openxml4j -// hyperlinks.add( -// new XSSFHyperlink(hyperlink, hyperRel) -// ); + hyperlinks.add( + new XSSFHyperlink(hyperlink, hyperRel) + ); } } 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 57b088dcb5..2c469c49b3 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java @@ -23,6 +23,10 @@ import java.io.File; import junit.framework.TestCase; +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.openxml4j.opc.Package; public class TestXSSFHyperlink extends TestCase { @@ -52,8 +56,9 @@ public class TestXSSFHyperlink extends TestCase { XSSFSheet sheet = (XSSFSheet)workbook.getSheetAt(0); - // TODO - check hyperlinks - //assertEquals(4, sheet.getNumHyperlinks()); + // Check the hyperlinks + assertEquals(4, sheet.getNumHyperlinks()); + doTestHyperlinkContents(sheet); } public void testLoadSave() throws Exception { @@ -64,9 +69,14 @@ public class TestXSSFHyperlink extends TestCase { assertTrue(xml.exists()); XSSFWorkbook workbook = new XSSFWorkbook(xml.toString()); + CreationHelper createHelper = workbook.getCreationHelper(); assertEquals(3, workbook.getNumberOfSheets()); + XSSFSheet sheet = (XSSFSheet)workbook.getSheetAt(0); - // TODO - check hyperlinks + // Check hyperlinks + assertEquals(4, sheet.getNumHyperlinks()); + doTestHyperlinkContents(sheet); + // Write out, and check ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -79,8 +89,99 @@ public class TestXSSFHyperlink extends TestCase { assertNotNull(wb2.getSheetAt(0)); assertNotNull(wb2.getSheetAt(1)); assertNotNull(wb2.getSheetAt(2)); + + sheet = (XSSFSheet)wb2.getSheetAt(0); - // TODO + + // Check hyperlinks again + assertEquals(4, sheet.getNumHyperlinks()); + doTestHyperlinkContents(sheet); + + + // Add one more, and re-check + Row r17 = sheet.createRow(17); + Cell r17c = r17.createCell(2); + + Hyperlink hyperlink = createHelper.createHyperlink(Hyperlink.LINK_URL); + hyperlink.setAddress("http://poi.apache.org/spreadsheet/"); + hyperlink.setLabel("POI SS Link"); + r17c.setHyperlink(hyperlink); + + assertEquals(5, sheet.getNumHyperlinks()); + doTestHyperlinkContents(sheet); + + assertEquals(Hyperlink.LINK_URL, + sheet.getRow(17).getCell(2).getHyperlink().getType()); + assertEquals("POI SS Link", + sheet.getRow(17).getCell(2).getHyperlink().getLabel()); + assertEquals("http://poi.apache.org/spreadsheet/", + sheet.getRow(17).getCell(2).getHyperlink().getAddress()); + + + // Save and re-load once more + baos = new ByteArrayOutputStream(); + wb2.write(baos); + bais = new ByteArrayInputStream(baos.toByteArray()); + + + XSSFWorkbook wb3 = new XSSFWorkbook(Package.open(bais)); + assertEquals(3, wb3.getNumberOfSheets()); + assertNotNull(wb3.getSheetAt(0)); + assertNotNull(wb3.getSheetAt(1)); + assertNotNull(wb3.getSheetAt(2)); + + sheet = (XSSFSheet)wb3.getSheetAt(0); + + assertEquals(5, sheet.getNumHyperlinks()); + doTestHyperlinkContents(sheet); + + assertEquals(Hyperlink.LINK_URL, + sheet.getRow(17).getCell(2).getHyperlink().getType()); + assertEquals("POI SS Link", + sheet.getRow(17).getCell(2).getHyperlink().getLabel()); + assertEquals("http://poi.apache.org/spreadsheet/", + sheet.getRow(17).getCell(2).getHyperlink().getAddress()); + } + + /** + * Only for WithMoreVariousData.xlsx ! + */ + private void doTestHyperlinkContents(XSSFSheet sheet) { + assertNotNull(sheet.getRow(3).getCell(2).getHyperlink()); + assertNotNull(sheet.getRow(14).getCell(2).getHyperlink()); + assertNotNull(sheet.getRow(15).getCell(2).getHyperlink()); + assertNotNull(sheet.getRow(16).getCell(2).getHyperlink()); + + // First is a link to poi + assertEquals(Hyperlink.LINK_URL, + sheet.getRow(3).getCell(2).getHyperlink().getType()); + assertEquals(null, + sheet.getRow(3).getCell(2).getHyperlink().getLabel()); + assertEquals("http://poi.apache.org/", + sheet.getRow(3).getCell(2).getHyperlink().getAddress()); + + // Next is an internal doc link + assertEquals(Hyperlink.LINK_DOCUMENT, + sheet.getRow(14).getCell(2).getHyperlink().getType()); + assertEquals("Internal hyperlink to A2", + sheet.getRow(14).getCell(2).getHyperlink().getLabel()); + assertEquals("Sheet1!A2", + sheet.getRow(14).getCell(2).getHyperlink().getAddress()); + + // Next is a file + assertEquals(Hyperlink.LINK_FILE, + sheet.getRow(15).getCell(2).getHyperlink().getType()); + assertEquals(null, + sheet.getRow(15).getCell(2).getHyperlink().getLabel()); + assertEquals("WithVariousData.xlsx", + sheet.getRow(15).getCell(2).getHyperlink().getAddress()); + + // Last is a mailto + assertEquals(Hyperlink.LINK_EMAIL, + sheet.getRow(16).getCell(2).getHyperlink().getType()); + assertEquals(null, + sheet.getRow(16).getCell(2).getHyperlink().getLabel()); + assertEquals("mailto:dev@poi.apache.org?subject=XSSF%20Hyperlinks", + sheet.getRow(16).getCell(2).getHyperlink().getAddress()); } - }