You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ye...@apache.org on 2008/02/07 09:57:00 UTC

svn commit: r619310 - in /poi/trunk/src: documentation/content/xdocs/ documentation/content/xdocs/hssf/ examples/src/org/apache/poi/hssf/usermodel/examples/ java/org/apache/poi/hssf/record/ java/org/apache/poi/hssf/usermodel/ testcases/org/apache/poi/h...

Author: yegor
Date: Thu Feb  7 00:56:59 2008
New Revision: 619310

URL: http://svn.apache.org/viewvc?rev=619310&view=rev
Log:
support for excel hypelrinks

Added:
    poi/trunk/src/examples/src/org/apache/poi/hssf/usermodel/examples/Hyperlinks.java   (with props)
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java   (with props)
Modified:
    poi/trunk/src/documentation/content/xdocs/changes.xml
    poi/trunk/src/documentation/content/xdocs/hssf/quick-guide.xml
    poi/trunk/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java

Modified: poi/trunk/src/documentation/content/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/changes.xml?rev=619310&r1=619309&r2=619310&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/changes.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/changes.xml Thu Feb  7 00:56:59 2008
@@ -36,6 +36,7 @@
 
 		<!-- Don't forget to update status.xml too! -->
         <release version="3.1-beta1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="add">37923 - Support for Excel hyperlinks</action>
            <action dev="POI-DEVELOPERS" type="add">Implement hashCode() and equals(obj) on HSSFFont and HSSFCellStyle</action>
            <action dev="POI-DEVELOPERS" type="fix">44345 - Implement CountA, CountIf, Index, Rows and Columns functions</action>
            <action dev="POI-DEVELOPERS" type="fix">44336 - Properly escape sheet names as required when figuring out the text of formulas</action>

Modified: poi/trunk/src/documentation/content/xdocs/hssf/quick-guide.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/hssf/quick-guide.xml?rev=619310&r1=619309&r2=619310&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/hssf/quick-guide.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/hssf/quick-guide.xml Thu Feb  7 00:56:59 2008
@@ -69,6 +69,7 @@
                     <li><link href="#NamedRanges">Named Ranges and Named Cells</link></li>
                     <li><link href="#CellComments">How to set cell comments</link></li>
                     <li><link href="#Autofit">How to adjust column width to fit the contents</link></li>
+                    <li><link href="#Hyperlinks">Hyperlinks</link></li>
                 </ul>
             </section>
             <section><title>Features</title>
@@ -1321,6 +1322,76 @@
     set the following system property: <code> java.awt.headless=true </code>
     (either via <code>-Djava.awt.headless=true</code> startup parameter or via <code>System.setProperty("java.awt.headless", "true")</code>).
         </warning>
+     </section>
+     <anchor id="Hyperlinks"/>
+     <section><title>How to read hyperlinks</title>
+        <source>
+    HSSFSheet sheet = workbook.getSheetAt(0);
+
+    HSSFCell cell = sheet.getRow(0).getCell((short)0);
+    HSSFHyperlink link = cell.getHyperlink();
+    if(link != null){
+        System.out.println(link.getAddress());
+    }
+      </source>
+     </section>
+     <section><title>How to create hyperlinks</title>
+        <source>
+    HSSFWorkbook wb = new HSSFWorkbook();
+
+    //cell style for hyperlinks
+    //by default hypelrinks are blue and underlined
+    HSSFCellStyle hlink_style = wb.createCellStyle();
+    HSSFFont hlink_font = wb.createFont();
+    hlink_font.setUnderline(HSSFFont.U_SINGLE);
+    hlink_font.setColor(HSSFColor.BLUE.index);
+    hlink_style.setFont(hlink_font);
+
+    HSSFCell cell;
+    HSSFSheet sheet = wb.createSheet("Hyperlinks");
+
+    //URL
+    cell = sheet.createRow(0).createCell((short)0);
+    cell.setCellValue("URL Link");
+    HSSFHyperlink link = new HSSFHyperlink(HSSFHyperlink.LINK_URL);
+    link.setAddress("http://poi.apache.org/");
+    cell.setHyperlink(link);
+    cell.setCellStyle(hlink_style);
+
+    //link to a file in the current directory
+    cell = sheet.createRow(1).createCell((short)0);
+    cell.setCellValue("File Link");
+    link = new HSSFHyperlink(HSSFHyperlink.LINK_FILE);
+    link.setAddress("link1.xls");
+    cell.setHyperlink(link);
+    cell.setCellStyle(hlink_style);
+
+    //e-mail link
+    cell = sheet.createRow(2).createCell((short)0);
+    cell.setCellValue("Email Link");
+    link = new HSSFHyperlink(HSSFHyperlink.LINK_EMAIL);
+    //note, if subject contains white spaces, make sure they are url-encoded
+    link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
+    cell.setHyperlink(link);
+    cell.setCellStyle(hlink_style);
+
+    //link to a place in this workbook
+
+    //create a target sheet and cell
+    HSSFSheet sheet2 = wb.createSheet("Target Sheet");
+    sheet2.createRow(0).createCell((short)0).setCellValue("Target Cell");
+
+    cell = sheet.createRow(3).createCell((short)0);
+    cell.setCellValue("Worksheet Link");
+    link = new HSSFHyperlink(HSSFHyperlink.LINK_DOCUMENT);
+    link.setAddress("'Target Sheet'!A1");
+    cell.setHyperlink(link);
+    cell.setCellStyle(hlink_style);
+
+    FileOutputStream out = new FileOutputStream("hssf-links.xls");
+    wb.write(out);
+    out.close();
+    </source>
      </section>
 
     </body>

Modified: poi/trunk/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/status.xml?rev=619310&r1=619309&r2=619310&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/status.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/status.xml Thu Feb  7 00:56:59 2008
@@ -33,6 +33,7 @@
 	<!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.1-beta1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="add">37923 - Support for Excel hyperlinks</action>
            <action dev="POI-DEVELOPERS" type="add">Implement hashCode() and equals(obj) on HSSFFont and HSSFCellStyle</action>
            <action dev="POI-DEVELOPERS" type="fix">44345 - Implement CountA, CountIf, Index, Rows and Columns functions</action>
            <action dev="POI-DEVELOPERS" type="fix">44336 - Properly escape sheet names as required when figuring out the text of formulas</action>

Added: poi/trunk/src/examples/src/org/apache/poi/hssf/usermodel/examples/Hyperlinks.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/examples/src/org/apache/poi/hssf/usermodel/examples/Hyperlinks.java?rev=619310&view=auto
==============================================================================
--- poi/trunk/src/examples/src/org/apache/poi/hssf/usermodel/examples/Hyperlinks.java (added)
+++ poi/trunk/src/examples/src/org/apache/poi/hssf/usermodel/examples/Hyperlinks.java Thu Feb  7 00:56:59 2008
@@ -0,0 +1,91 @@
+
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.usermodel.examples;
+
+import org.apache.poi.hssf.usermodel.*;
+import org.apache.poi.hssf.util.HSSFColor;
+
+import java.io.IOException;
+import java.io.FileOutputStream;
+
+/**
+ * Demonstrates how to create hyperlinks.
+ *
+ * @author Yegor Kozlov (yegor at apach.org)
+ */
+public class Hyperlinks {
+
+    public static void main(String[] args) throws IOException  {
+        HSSFWorkbook wb = new HSSFWorkbook();
+
+        //cell style for hyperlinks
+        //by default hypelrinks are blue and underlined
+        HSSFCellStyle hlink_style = wb.createCellStyle();
+        HSSFFont hlink_font = wb.createFont();
+        hlink_font.setUnderline(HSSFFont.U_SINGLE);
+        hlink_font.setColor(HSSFColor.BLUE.index);
+        hlink_style.setFont(hlink_font);
+
+        HSSFCell cell;
+        HSSFSheet sheet = wb.createSheet("Hyperlinks");
+
+        //URL
+        cell = sheet.createRow(0).createCell((short)0);
+        cell.setCellValue("URL Link");
+        HSSFHyperlink link = new HSSFHyperlink(HSSFHyperlink.LINK_URL);
+        link.setAddress("http://poi.apache.org/");
+        cell.setHyperlink(link);
+        cell.setCellStyle(hlink_style);
+
+        //link to a file in the current directory
+        cell = sheet.createRow(1).createCell((short)0);
+        cell.setCellValue("File Link");
+        link = new HSSFHyperlink(HSSFHyperlink.LINK_FILE);
+        link.setAddress("link1.xls");
+        cell.setHyperlink(link);
+        cell.setCellStyle(hlink_style);
+
+        //e-mail link
+        cell = sheet.createRow(2).createCell((short)0);
+        cell.setCellValue("Email Link");
+        link = new HSSFHyperlink(HSSFHyperlink.LINK_EMAIL);
+        //note, if subject contains white spaces, make sure they are url-encoded
+        link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
+        cell.setHyperlink(link);
+        cell.setCellStyle(hlink_style);
+
+        //link to a place in this workbook
+
+        //create a target sheet and cell
+        HSSFSheet sheet2 = wb.createSheet("Target Sheet");
+        sheet2.createRow(0).createCell((short)0).setCellValue("Target Cell");
+
+        cell = sheet.createRow(3).createCell((short)0);
+        cell.setCellValue("Worksheet Link");
+        link = new HSSFHyperlink(HSSFHyperlink.LINK_DOCUMENT);
+        link.setAddress("'Target Sheet'!A1");
+        cell.setHyperlink(link);
+        cell.setCellStyle(hlink_style);
+
+        FileOutputStream out = new FileOutputStream("hssf-links.xls");
+        wb.write(out);
+        out.close();
+
+    }
+}

Propchange: poi/trunk/src/examples/src/org/apache/poi/hssf/usermodel/examples/Hyperlinks.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java?rev=619310&r1=619309&r2=619310&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java Thu Feb  7 00:56:59 2008
@@ -1,29 +1,27 @@
 /* ====================================================================
- Copyright 2002-2004   Apache Software Foundation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ==================================================================== */
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
 
 package org.apache.poi.hssf.record;
 
 import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import java.util.Arrays;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.StringUtil;
+import org.apache.poi.util.HexDump;
 
 /**
  * The <code>HyperlinkRecord</code> wraps an HLINK-record 
@@ -31,146 +29,283 @@
  * Supports only external links for now (eg http://) 
  *
  * @author      Mark Hissink Muller <a href="mailto:mark@hissinkmuller.nl >mark&064;hissinkmuller.nl</a>
+ * @author      Yegor Kozlov (yegor at apache dot org)
  */
-public class HyperlinkRecord extends Record implements CellValueRecordInterface
-{
-    /** Indicates the URL in the Record */
-    private static byte[] GUID_OF_URL_MONIKER =
-    { -32, -55, -22, 121, -7, -70, -50, 17, -116, -126, 0, -86, 0, 75, -87, 11 };
-
-    /** Indicates the STD_LINK in the Record */
-    // MHM: to be added when necessary
-    private static byte[] GUID_OF_STD_LINK =  {};
+public class HyperlinkRecord extends Record {
+    /**
+     * Link flags
+     */
+    protected static final int  HLINK_URL    = 0x01;  // File link or URL.
+    protected static final int  HLINK_ABS    = 0x02;  // Absolute path.
+    protected static final int  HLINK_LABEL  = 0x14;  // Has label.
+    protected static final int  HLINK_PLACE  = 0x08;  // Place in worksheet.
 
-    /** Logger */
-    public static final Log log = LogFactory.getLog(HyperlinkRecord.class);
 
-    // quick and dirty
-    private static final boolean _DEBUG_ = true;
+    protected final static byte[] STD_MONIKER = {(byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
+                                                 (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B };
+    protected final static byte[] URL_MONIKER = {(byte)0xE0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
+                                                 (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B };
+    protected final static byte[] FILE_MONIKER = {0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46};
 
+    /**
+     * Tail of a URL link
+     */
+    protected final static byte[] URL_TAIL = {0x79, 0x58, (byte)0x81, (byte)0xF4, 0x3B, 0x1D, 0x7F, 0x48, (byte)0xAF, 0x2C,
+                                              (byte)0x82, 0x5D, (byte)0xC4, (byte)0x85, 0x27, 0x63, 0x00, 0x00, 0x00,
+                                               0x00, (byte)0xA5, (byte)0xAB, 0x00, 0x00};
+
+    /**
+     * Tail of a file link
+     */
+    protected final static byte[] FILE_TAIL = {(byte)0xFF, (byte)0xFF, (byte)0xAD, (byte)0xDE, 0x00, 0x00, 0x00, 0x00,
+                                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
     public final static short sid = 0x1b8;
 
-    private short field_1_unknown;
-    private int field_2_row;
-    private short field_3_column;
-    private short field_4_xf_index;
-    private byte[] field_5_unknown;
-    private int field_6_label_opts;
-    private int field_7_url_len;
-    private int field_8_label_len;
-    private String field_9_label;
-    private byte[] field_10_unknown;
-    private int field_11_url_opts;
-    private String field_12_url;
+    /**
+     * First row of the hyperlink
+     */
+    private int rwFirst;
+
+    /**
+     * Last row of the hyperlink
+     */
+    private int rwLast;
+
+    /**
+     * First column of the hyperlink
+     */
+    private short colFirst;
 
-    /** Blank Constructor */
+    /**
+     * Last column of the hyperlink
+     */
+    private short colLast;
+
+    /**
+     * 16-byte GUID
+     */
+    private byte[] guid;
+
+    /**
+     * Some sort of options. Seems to always equal 2
+     */
+    private int label_opts;
+
+    /**
+     * Some sort of options for file links.
+     */
+    private short file_opts;
+
+    /**
+     * Link options. Can include any of HLINK_* flags.
+     */
+    private int link_opts;
+
+    /**
+     * Test label
+     */
+    private String label;
+
+    /**
+     * Moniker. Makes sense only for URL and file links
+     */
+    private byte[] moniker;
+
+    /**
+     * Link
+     */
+    private String address;
+
+    /**
+     * Remaining bytes
+     */
+    private byte[] tail;
+
+    /**
+     * Create a new hyperlink
+     */
     public HyperlinkRecord()
     {
+
     }
 
-    /** Real Constructor */
+    /**
+     * Read hyperlink from input stream
+     *
+     * @param in the stream to read from
+     */
     public HyperlinkRecord(RecordInputStream in)
     {
         super(in);
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.CellValueRecordInterface#getColumn()
+    /**
+     * Return the column of the first cell that contains the hyperlink
+     *
+     * @return the 0-based column of the first cell that contains the hyperlink
      */
-    public short getColumn()
+   public short getFirstColumn()
     {
-        return field_3_column;
+        return colFirst;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.CellValueRecordInterface#getRow()
+    /**
+     * Set the column of the first cell that contains the hyperlink
+     *
+     * @param col the 0-based column of the first cell that contains the hyperlink
      */
-    public int getRow()
+    public void setFirstColumn(short col)
+    {
+        this.colFirst = col;
+    }
+
+    /**
+     * Set the column of the last cell that contains the hyperlink
+     *
+     * @return the 0-based column of the last cell that contains the hyperlink
+    */
+    public short getLastColumn()
     {
-        return field_2_row;
+        return colLast;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.CellValueRecordInterface#getXFIndex()
+    /**
+     * Set the column of the last cell that contains the hyperlink
+     *
+     * @param col the 0-based column of the last cell that contains the hyperlink
      */
-    public short getXFIndex()
+    public void setLastColumn(short col)
     {
-        return field_4_xf_index;
+        this.colLast = col;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.CellValueRecordInterface#isAfter(org.apache.poi.hssf.record.CellValueRecordInterface)
+    /**
+     * Return the row of the first cell that contains the hyperlink
+     *
+     * @return the 0-based row of the first cell that contains the hyperlink
      */
-    public boolean isAfter(CellValueRecordInterface i)
+    public int getFirstRow()
     {
-        if (this.getRow() < i.getRow())
-        {
-            return false;
-        }
-        if ((this.getRow() == i.getRow()) && (this.getColumn() < i.getColumn()))
-        {
-            return false;
-        }
-        if ((this.getRow() == i.getRow()) && (this.getColumn() == i.getColumn()))
-        {
-            return false;
-        }
-        return true;
+        return rwFirst;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.CellValueRecordInterface#isBefore(org.apache.poi.hssf.record.CellValueRecordInterface)
+    /**
+     * Set the row of the first cell that contains the hyperlink
+     *
+     * @param row the 0-based row of the first cell that contains the hyperlink
      */
-    public boolean isBefore(CellValueRecordInterface i)
+    public void setFirstRow(int row)
     {
-        if (this.getRow() > i.getRow())
-        {
-            return false;
-        }
-        if ((this.getRow() == i.getRow()) && (this.getColumn() > i.getColumn()))
-        {
-            return false;
-        }
-        if ((this.getRow() == i.getRow()) && (this.getColumn() == i.getColumn()))
-        {
-            return false;
-        }
-        return true;
+        this.rwFirst = row;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.CellValueRecordInterface#isEqual(org.apache.poi.hssf.record.CellValueRecordInterface)
+    /**
+     * Return the row of the last cell that contains the hyperlink
+     *
+     * @return the 0-based row of the last cell that contains the hyperlink
      */
-    public boolean isEqual(CellValueRecordInterface i)
+    public int getLastRow()
     {
-        return ((this.getRow() == i.getRow()) && (this.getColumn() == i.getColumn()));
+        return rwLast;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.CellValueRecordInterface#setColumn(short)
+    /**
+     * Set the row of the last cell that contains the hyperlink
+     *
+     * @param row the 0-based row of the last cell that contains the hyperlink
      */
-    public void setColumn(short col)
+    public void setLastRow(int row)
     {
-        this.field_3_column = col;
+        this.rwLast = row;
+    }
 
+    /**
+     * Returns a 16-byte guid identifier. Seems to always equal {@link STD_MONIKER}
+     *
+     * @return 16-byte guid identifier
+     */
+    public byte[] getGuid()
+    {
+        return guid;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.CellValueRecordInterface#setRow(int)
+    /**
+     * Returns a 16-byte moniker.
+     *
+     * @return 16-byte moniker
      */
-    public void setRow(int row)
+    public byte[] getMoniker()
     {
-        this.field_2_row = row;
+        return moniker;
+    }
 
+
+    /**
+     * Return text label for this hyperlink
+     *
+     * @return  text to display
+     */
+    public String getLabel()
+    {
+        int idx = label.indexOf('\u0000');
+        return idx == -1 ? label : label.substring(0, idx);
+    }
+
+    /**
+     * Sets text label for this hyperlink
+     *
+     * @param label text label for this hyperlink
+     */
+     public void setLabel(String label)
+    {
+        this.label = label + '\u0000';
+    }
+
+    /**
+     * Hypelink address. Depending on the hyperlink type it can be URL, e-mail, patrh to a file, etc.
+     *
+     * @return  the address of this hyperlink
+     */
+    public String getAddress()
+    {
+        int idx = address.indexOf('\u0000');
+        return idx == -1 ? address : address.substring(0, idx);
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.CellValueRecordInterface#setXFIndex(short)
+    /**
+     * Hypelink address. Depending on the hyperlink type it can be URL, e-mail, patrh to a file, etc.
+     *
+     * @param address  the address of this hyperlink
      */
-    public void setXFIndex(short xf)
+    public void setAddress(String address)
     {
-        this.field_4_xf_index = xf;
+        this.address = address + '\u0000';
+    }
 
+    /**
+     * Link options. Must be a combination of HLINK_* constants.
+     */
+    public int getLinkOptions(){
+        return link_opts;
+    }
+
+    /**
+     * Label options
+     */
+    public int getLabelOptions(){
+        return label_opts;
+    }
+
+    /**
+     * Options for a file link
+     */
+    public int getFileOptions(){
+        return file_opts;
+    }
+
+    public byte[] getTail(){
+        return tail;
     }
 
     /**
@@ -178,57 +313,56 @@
      */
     protected void fillFields(RecordInputStream in)
     {
-//    	System.err.println(in.currentSid);
-//    	System.err.println(in.currentLength);
-//    	for(int i=0; i<300; i++) {
-//    		System.err.println(in.readByte());
-//    	}
-//    	if(1==1)
-//    		throw new IllegalArgumentException("");
-    	
-        field_1_unknown = in.readShort();
-        field_2_row = in.readUShort(); 
-        field_3_column = in.readShort();
-        field_4_xf_index = in.readShort();
-        
-        // Next up is 16 bytes we don't get
-        field_5_unknown = new byte[16];
-        try {
-        in.read(field_5_unknown);
-        } catch(IOException e) { throw new IllegalStateException(e.getMessage()); }
-        
-        // Some sort of opts
-        field_6_label_opts = in.readInt();
-        
-        // Now for lengths, in characters
-        field_7_url_len = in.readInt();
-        field_8_label_len = in.readInt();
-        
-        // Now we have the label, as little endian unicode,
-        //  with a trailing \0
-        field_9_label = in.readUnicodeLEString(field_8_label_len);
-        
-        // Next up is some more data we can't make sense of
-        field_10_unknown = new byte[16];
         try {
-        in.read(field_10_unknown);
-        } catch(IOException e) { throw new IllegalStateException(e.getMessage()); }
-        
-        // Might need to nudge the length by one byte
-        // This is an empirical hack!
-        field_11_url_opts = in.readInt();
-        if(field_11_url_opts == 44) {
-        	field_7_url_len--;
+            rwFirst = in.readShort();
+            rwLast = in.readUShort();
+            colFirst = in.readShort();
+            colLast = in.readShort();
+
+            // 16-byte GUID
+            guid = new byte[16];
+            in.read(guid);
+
+            label_opts = in.readInt();
+            link_opts = in.readInt();
+
+            if ((link_opts & HLINK_LABEL) != 0){
+                int label_len = in.readInt();
+                label = in.readUnicodeLEString(label_len);
+            }
+
+            if ((link_opts & HLINK_URL) != 0){
+                moniker = new byte[16];
+                in.read(moniker);
+
+                if(Arrays.equals(URL_MONIKER, moniker)){
+                    int len = in.readInt();
+
+                    address = in.readUnicodeLEString(len/2);
+
+                    tail = in.readRemainder();
+                } else if (Arrays.equals(FILE_MONIKER, moniker)){
+                    file_opts = in.readShort();
+
+                    int len = in.readInt();
+
+                    byte[] path_bytes = new byte[len];
+                    in.read(path_bytes);
+
+                    address = new String(path_bytes);
+
+                    tail = in.readRemainder();
+                }
+            } else if((link_opts & HLINK_PLACE) != 0){
+                int len = in.readInt();
+                address = in.readUnicodeLEString(len);
+            }
+        } catch (IOException e){
+            throw new RuntimeException(e);
         }
-        
-        // Finally it's the URL
-        int strlen = field_7_url_len > (in.remaining()/2) ? (in.remaining()/2) : field_7_url_len;
-        field_12_url = in.readUnicodeLEString(strlen);
-    }
-    
-    /* (non-Javadoc)
-     * @see org.apache.poi.hssf.record.Record#getSid()
-     */
+
+    }
+
     public short getSid()
     {
         return HyperlinkRecord.sid;
@@ -244,55 +378,75 @@
 
     public int serialize(int offset, byte[] data)
     {
-        LittleEndian.putShort(data, 0 + offset, sid);
-        LittleEndian.putShort(data, 2 + offset,
-                              ( short )(getRecordSize()-4));
-        LittleEndian.putShort(data, 4 + offset, field_1_unknown);
-        LittleEndian.putUShort(data, 6 + offset, field_2_row);
-        LittleEndian.putShort(data, 8 + offset, field_3_column);
-        LittleEndian.putShort(data, 10 + offset, field_4_xf_index);
-        
-        offset += 12;
-        for(int i=0; i<field_5_unknown.length; i++) {
-        	data[offset] = field_5_unknown[i];
-        	offset++;
+        int pos = offset;
+        LittleEndian.putShort(data, pos, sid); pos += 2;
+        LittleEndian.putShort(data, pos, ( short )(getRecordSize()-4)); pos += 2;
+        LittleEndian.putUShort(data, pos, rwFirst); pos += 2;
+        LittleEndian.putUShort(data, pos, rwLast); pos += 2;
+        LittleEndian.putShort(data, pos, colFirst); pos += 2;
+        LittleEndian.putShort(data, pos, colLast); pos += 2;
+
+        System.arraycopy(guid, 0, data, pos, guid.length); pos += guid.length;
+
+        LittleEndian.putInt(data, pos, label_opts); pos += 4;
+        LittleEndian.putInt(data, pos, link_opts); pos += 4;
+
+        if ((link_opts & HLINK_LABEL) != 0){
+            LittleEndian.putInt(data, pos, label.length()); pos += 4;
+            StringUtil.putUnicodeLE(label, data, pos);  pos += label.length()*2;
         }
-        
-        LittleEndian.putInt(data, offset, field_6_label_opts);
-        offset += 4;
-        LittleEndian.putInt(data, offset, field_7_url_len);
-        offset += 4;
-        LittleEndian.putInt(data, offset, field_8_label_len);
-        offset += 4;
-        StringUtil.putUnicodeLE(field_9_label, data, offset);
-        offset += field_9_label.length()*2;
-
-        for(int i=0; i<field_10_unknown.length; i++) {
-        	data[offset] = field_10_unknown[i];
-        	offset++;
+        if ((link_opts & HLINK_URL) != 0){
+            System.arraycopy(moniker, 0, data, pos, moniker.length); pos += moniker.length;
+            if(Arrays.equals(URL_MONIKER, moniker)){
+                LittleEndian.putInt(data, pos, address.length()*2 + tail.length); pos += 4;
+                StringUtil.putUnicodeLE(address, data, pos);  pos += address.length()*2;
+                if(tail.length > 0){
+                    System.arraycopy(tail, 0, data, pos, tail.length); pos += tail.length;
+                }
+            } else if (Arrays.equals(FILE_MONIKER, moniker)){
+                LittleEndian.putShort(data, pos, file_opts); pos += 2;
+                LittleEndian.putInt(data, pos, address.length()); pos += 4;
+                byte[] bytes = address.getBytes();
+                System.arraycopy(bytes, 0, data, pos, bytes.length); pos += bytes.length;
+                if(tail.length > 0){
+                    System.arraycopy(tail, 0, data, pos, tail.length); pos += tail.length;
+                }
+            }
+        } else if((link_opts & HLINK_PLACE) != 0){
+            LittleEndian.putInt(data, pos, address.length()); pos += 4;
+            StringUtil.putUnicodeLE(address, data, pos);  pos += address.length()*2;
         }
-    	
-        LittleEndian.putInt(data, offset, field_11_url_opts);
-        offset += 4;
-        StringUtil.putUnicodeLE(field_12_url, data, offset);
-        
     	return getRecordSize();
     }
 
     public int getRecordSize()
     {
-    	// We have:
-    	// 4 shorts
-    	// junk
-    	// 3 ints
-    	// label
-    	// junk
-    	// int
-    	// url
-    	return 4 + 4*2 + field_5_unknown.length +
-    		3*4 + field_9_label.length()*2 +
-    		field_10_unknown.length + 4 +
-    		field_12_url.length()*2;
+        int size = 4;
+        size += 2 + 2 + 2 + 2;  //rwFirst, rwLast, colFirst, colLast
+        size += guid.length;
+        size += 4;  //label_opts
+        size += 4;  //link_opts
+        if ((link_opts & HLINK_LABEL) != 0){
+            size += 4;  //link length
+            size += label.length()*2;
+        }
+        if ((link_opts & HLINK_URL) != 0){
+            size += moniker.length;  //moniker length
+            if(Arrays.equals(URL_MONIKER, moniker)){
+                size += 4;  //address length
+                size += address.length()*2;
+                size += tail.length;
+            } else if (Arrays.equals(FILE_MONIKER, moniker)){
+                size += 2;  //file_opts
+                size += 4;  //address length
+                size += address.length();
+                size += tail.length;
+            }
+        } else if((link_opts & HLINK_PLACE) != 0){
+            size += 4;  //address length
+            size += address.length()*2;
+        }
+        return size;
     }
 
     public String toString()
@@ -300,71 +454,89 @@
         StringBuffer buffer = new StringBuffer();
 
         buffer.append("[HYPERLINK RECORD]\n");
-        buffer.append("    .row            = ").append(Integer.toHexString(getRow())).append("\n");
-        buffer.append("    .column         = ").append(Integer.toHexString(getColumn())).append("\n");
-        buffer.append("    .xfindex        = ").append(Integer.toHexString(getXFIndex())).append("\n");
-        buffer.append("    .label          = ").append(field_9_label).append("\n");
-        buffer.append("    .url            = ").append(field_12_url).append("\n");
+        buffer.append("    .rwFirst            = ").append(Integer.toHexString(getFirstRow())).append("\n");
+        buffer.append("    .rwLast         = ").append(Integer.toHexString(getLastRow())).append("\n");
+        buffer.append("    .colFirst            = ").append(Integer.toHexString(getFirstColumn())).append("\n");
+        buffer.append("    .colLast         = ").append(Integer.toHexString(getLastColumn())).append("\n");
+        buffer.append("    .guid        = ").append(HexDump.toHex(guid)).append("\n");
+        buffer.append("    .label_opts          = ").append(label_opts).append("\n");
+        buffer.append("    .label          = ").append(getLabel()).append("\n");
+        if((link_opts & HLINK_URL) != 0){
+            buffer.append("    .moniker          = ").append(HexDump.toHex(moniker)).append("\n");
+        }
+        buffer.append("    .address            = ").append(getAddress()).append("\n");
         buffer.append("[/HYPERLINK RECORD]\n");
         return buffer.toString();
     }
 
     /**
-     * @return Returns the label.
+     * Initialize a new url link
      */
-    public String getLabel()
-    {
-    	if(field_9_label.length() == 0) {
-    		return "";
-    	} else {
-    		// Trim off \0
-            return field_9_label.substring(0, field_9_label.length() - 1);
-    	}
+    public void newUrlLink(){
+        rwFirst = 0;
+        rwLast = 0;
+        colFirst = 0;
+        colLast = 0;
+        guid = STD_MONIKER;
+        label_opts = 0x2;
+        link_opts = HLINK_URL | HLINK_ABS | HLINK_LABEL;
+        label = "" + '\u0000';
+        moniker = URL_MONIKER;
+        address = "" + '\u0000';
+        tail = URL_TAIL;
     }
 
     /**
-     * @param label The label to set.
+     * Initialize a new file link
      */
-    public void setLabel(String label)
-    {
-        this.field_9_label = label + '\u0000';
-        this.field_8_label_len = field_9_label.length();
+    public void newFileLink(){
+        rwFirst = 0;
+        rwLast = 0;
+        colFirst = 0;
+        colLast = 0;
+        guid = STD_MONIKER;
+        label_opts = 0x2;
+        link_opts = HLINK_URL | HLINK_LABEL;
+        file_opts = 0;
+        label = "" + '\u0000';
+        moniker = FILE_MONIKER;
+        address = "" + '\0';
+        tail = FILE_TAIL;
     }
 
     /**
-     * @return Returns the Url.
+     * Initialize a new document link
      */
-    public URL getUrl() throws MalformedURLException
-    {
-        return new URL(getUrlString());
-    }
-    public String getUrlString()
-    {
-    	if(field_12_url.length() == 0) {
-    		return "";
-    	} else {
-    		// Trim off \0
-            return field_12_url.substring(0, field_12_url.length() - 1);
-    	}
+    public void newDocumentLink(){
+        rwFirst = 0;
+        rwLast = 0;
+        colFirst = 0;
+        colLast = 0;
+        guid = STD_MONIKER;
+        label_opts = 0x2;
+        link_opts = HLINK_LABEL | HLINK_PLACE;
+        label = "" + '\u0000';
+        moniker = FILE_MONIKER;
+        address = "" + '\0';
+        tail = new byte[]{};
+    }
+
+    public Object clone() {
+        HyperlinkRecord rec = new HyperlinkRecord();
+        rec.rwFirst = rwFirst;
+        rec.rwLast = rwLast;
+        rec.colFirst = colFirst;
+        rec.colLast = colLast;
+        rec.guid = guid;
+        rec.label_opts = label_opts;
+        rec.link_opts = link_opts;
+        rec.file_opts = file_opts;
+        rec.label = label;
+        rec.address = address;
+        rec.moniker = moniker;
+        rec.tail = tail;
+        return rec;
     }
 
-    /**
-     * @param url The url to set.
-     */
-    public void setUrl(URL url)
-    {
-    	setUrl(url.toString());
-    }
-    /**
-     * @param url The url to set.
-     */
-    public void setUrl(String url)
-    {
-        this.field_12_url = url + '\u0000';
-        this.field_7_url_len = field_12_url.length();
-    }
 
-    public int getOptions(){
-        return field_11_url_opts;
-    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java?rev=619310&r1=619309&r2=619310&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java Thu Feb  7 00:56:59 2008
@@ -1066,7 +1066,7 @@
             Record rec = ( Record ) it.next();
             if (rec instanceof HyperlinkRecord){
                 HyperlinkRecord link = (HyperlinkRecord)rec;
-                if(link.getColumn() == record.getColumn() && link.getRow() == record.getRow()){
+                if(link.getFirstColumn() == record.getColumn() && link.getFirstRow() == record.getRow()){
                     return new HSSFHyperlink(link);
                 }
             }
@@ -1080,6 +1080,25 @@
      * @param link hypelrink associated with this cell
      */
     public void setHyperlink(HSSFHyperlink link){
+        link.setFirstRow(record.getRow());
+        link.setLastRow(record.getRow());
+        link.setFirstColumn(record.getColumn());
+        link.setLastColumn(record.getColumn());
 
+        switch(link.getType()){
+            case HSSFHyperlink.LINK_EMAIL:
+            case HSSFHyperlink.LINK_URL:
+                link.setLabel("url");
+                break;
+            case HSSFHyperlink.LINK_FILE:
+                link.setLabel("file");
+                break;
+            case HSSFHyperlink.LINK_DOCUMENT:
+                link.setLabel("place");
+                break;
+        }
+
+        int eofLoc = sheet.findFirstRecordLocBySid( EOFRecord.sid );
+        sheet.getRecords().add( eofLoc, link.record );
     }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java?rev=619310&r1=619309&r2=619310&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java Thu Feb  7 00:56:59 2008
@@ -27,9 +27,9 @@
 import java.util.Iterator;
 
 /**
- * Represents a hyperlink.
+ * Represents an Excel hyperlink.
  *
- * @author Yegor Kozlov
+ * @author Yegor Kozlov (yegor at apache dot org)
  */
 public class HSSFHyperlink {
 
@@ -49,67 +49,145 @@
     public static final int LINK_EMAIL = 3;
 
     /**
-     * Unknown type
+     * Link to a file
      */
-    public static final int LINK_UNKNOWN = 4;
+    public static final int LINK_FILE = 4;
 
     /**
      * Low-level record object that stores the actual hyperlink data
      */
-    private HyperlinkRecord record = null;
+    protected HyperlinkRecord record = null;
 
+    /**
+     * If we create a new hypelrink remember its type
+     */
+    protected int link_type;
+
+    /**
+     * Construct a new hyperlink
+     *
+     * @param type the type of hyperlink to create
+     */
+    public HSSFHyperlink( int type )
+    {
+        this.link_type = type;
+        record = new HyperlinkRecord();
+        switch(type){
+            case LINK_URL:
+            case LINK_EMAIL:
+                record.newUrlLink();
+                break;
+            case LINK_FILE:
+                record.newFileLink();
+                break;
+            case LINK_DOCUMENT:
+                record.newDocumentLink();
+                break;
+        }
+    }
+
+    /**
+     * Initialize the hyperlink by a <code>HyperlinkRecord</code> record
+     *
+     * @param record
+     */
     protected HSSFHyperlink( HyperlinkRecord record )
     {
         this.record = record;
     }
 
     /**
-     * Return the row of the cell that contains the hyperlink
+     * Return the row of the first cell that contains the hyperlink
      *
      * @return the 0-based row of the cell that contains the hyperlink
      */
-    public int getRow(){
-        return record.getRow();
+    public int getFirstRow(){
+        return record.getFirstRow();
+    }
+
+    /**
+     * Set the row of the first cell that contains the hyperlink
+     *
+     * @param row the 0-based row of the first cell that contains the hyperlink
+     */
+    public void setFirstRow(int row){
+        record.setFirstRow(row);
+    }
+
+    /**
+     * Return the row of the last cell that contains the hyperlink
+     *
+     * @return the 0-based row of the last cell that contains the hyperlink
+     */
+    public int getLastRow(){
+        return record.getLastRow();
+    }
+
+    /**
+     * Set the row of the last cell that contains the hyperlink
+     *
+     * @param row the 0-based row of the last cell that contains the hyperlink
+     */
+    public void setLastRow(int row){
+        record.setLastRow(row);
+    }
+
+    /**
+     * Return the column of the first cell that contains the hyperlink
+     *
+     * @return the 0-based column of the first cell that contains the hyperlink
+     */
+    public short getFirstColumn(){
+        return record.getFirstColumn();
     }
 
     /**
-     * Set the row of the cell that contains the hyperlink
+     * Set the column of the first cell that contains the hyperlink
      *
-     * @param row the 0-based row of the cell that contains the hyperlink
+     * @param col the 0-based column of the first cell that contains the hyperlink
      */
-    public void setRow(int row){
-        record.setRow(row);
+    public void setFirstColumn(short col){
+        record.setFirstColumn(col);
     }
 
     /**
-     * Return the column of the cell that contains the hyperlink
+     * Return the column of the last cell that contains the hyperlink
      *
-     * @return the 0-based column of the cell that contains the hyperlink
+     * @return the 0-based column of the last cell that contains the hyperlink
      */
-    public short getColumn(){
-        return record.getColumn();
+    public short getLastColumn(){
+        return record.getLastColumn();
     }
 
     /**
-     * Set the column of the cell that contains the hyperlink
+     * Set the column of the last cell that contains the hyperlink
      *
-     * @param col the 0-based column of the cell that contains the hyperlink
+     * @param col the 0-based column of the last cell that contains the hyperlink
      */
-    public void setColumn(short col){
-        record.setColumn(col);
+    public void setLastColumn(short col){
+        record.setLastColumn(col);
     }
 
     /**
-     * Hypelink address. Depending on the hyperlink type it can be URL, e-mail, etc.
+     * Hypelink address. Depending on the hyperlink type it can be URL, e-mail, patrh to a file, etc.
      *
      * @return  the address of this hyperlink
      */
     public String getAddress(){
-        return record.getUrlString();
+        return record.getAddress();
     }
 
     /**
-     * Return text to display for this hyperlink
+     * Hypelink address. Depending on the hyperlink type it can be URL, e-mail, patrh to a file, etc.
+     *
+     * @param address  the address of this hyperlink
+     */
+    public void setAddress(String address){
+        record.setAddress(address);
+    }
+
+    /**
+     * Return text label for this hyperlink
      *
      * @return  text to display
      */
@@ -118,11 +196,20 @@
     }
 
     /**
+     * Sets text label for this hyperlink
+     *
+     * @param label text label for this hyperlink
+     */
+    public void setLabel(String label){
+        record.setLabel(label);
+    }
+
+    /**
      * Return the type of this hyperlink
      *
      * @return the type of this hyperlink
      */
-    public int getType(){
-        throw new RuntimeException("Not implemented");
+    protected int getType(){
+        return link_type;
     }
 }

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java?rev=619310&r1=619309&r2=619310&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java Thu Feb  7 00:56:59 2008
@@ -18,114 +18,311 @@
 
 import java.io.ByteArrayInputStream;
 import java.net.URL;
+import java.util.Arrays;
 
 import junit.framework.TestCase;
 
+/**
+ * Test HyperlinkRecord
+ *
+ * @author Nick Burch
+ * @author Yegor Kozlov
+ */
 public class TestHyperlinkRecord extends TestCase {
-	protected void setUp() throws Exception {
-		super.setUp();
-	}
-
-	private byte[] data = new byte[] { 
-		-72, 1, 110, 0,
-		// ??, Row, col, xf
-		6, 0, 3, 0,	2, 0, 2, 0, 
-		
-		// ??
-		-48, -55, -22, 121, -7, -70, -50, 17, 
-		-116, -126, 0, -86, 0, 75, -87, 11, 
-		2, 0, 0, 0, 
-		
-		// URL length
-		23, 0, 0, 0, 
-		
-		// Label length
-		4, 0, 0, 0,
-		
-		// Label
-		76, 0, 44, 0, 65, 0, 0, 0, 
-		
-		// ??
-		-32, -55, -22, 121, -7, -70, -50, 17,
-		-116, -126, 0, -86, 0, 75, -87, 11, 
-		46, 0, 0, 0,
-		
-		// URL
-		104, 0, 116, 0, 116, 0, 112, 0, 58, 0, 47, 0, 47, 0, 119,
-		0, 119, 0, 119, 0, 46, 0, 108, 0, 97, 0, 107, 0, 105,
-		0, 110, 0, 103, 0, 115, 0, 46, 0, 99, 0, 111, 0,
-		109, 0, 
-		0, 0 };
-	
-	private byte[] data2 = new byte[] {
-		-72, 1, -126, 0,
-		// ??, Row, col, xf
-		2, 0, 2, 0, 4, 0, 4, 0,
-
-		// ??
-		-48, -55, -22, 121, -7, -70, -50, 17,
-		-116, -126, 0, -86, 0, 75, -87, 11,
-		2, 0, 0, 0,
-		
-		// URL and Label lengths
-		23, 0, 0, 0,
-		15, 0, 0, 0,
-
-		// Label
-		83, 0, 116, 0, 97, 0, 99, 0, 105, 0,
-		101, 0, 64, 0, 65, 0, 66, 0, 67, 0,
-		46, 0, 99, 0, 111, 0, 109, 0, 0, 0,
-
-		// ??
-		-32, -55, -22, 121, -7, -70, -50, 17,
-		-116, -126, 0, -86, 0, 75, -87, 11,
-		44, 0, 0, 0,
-
-		// URL
-		109, 0, 97, 0, 105, 0, 108, 0, 116, 0,
-		111, 0, 58, 0, 83, 0, 116, 0, 97, 0,
-		99, 0, 105, 0, 101, 0, 64, 0, 65, 0,
-		66, 0, 67, 0, 46, 0, 99, 0, 111, 0,
-		109, 0, 0, 0 };
-
-	public void testRecordParsing() throws Exception {
-        RecordInputStream inp = new RecordInputStream(
-                new ByteArrayInputStream(data)
-        );
-        inp.nextRecord();
-
-        HyperlinkRecord r = new HyperlinkRecord(inp);
-        
-        assertEquals(3, r.getRow());
-        assertEquals(2, r.getColumn());
-        assertEquals(2, r.getXFIndex());
-        
-        assertEquals("L,A", r.getLabel());
-        assertEquals("http://www.lakings.com", r.getUrlString());
-        assertEquals(new URL("http://www.lakings.com"), r.getUrl());
-        
-        // Check it serialises as expected
-        assertEquals(data.length, r.getRecordSize());
-        byte[] d = r.serialize();
-        assertEquals(data.length, d.length);
-        for(int i=0; i<data.length; i++) {
-        	assertEquals(data[i], d[i]);
+
+    //link to http://www.lakings.com/
+    byte[] data1 = { 0x02, 0x00,    //First row of the hyperlink
+                     0x02, 0x00,    //Last row of the hyperlink
+                     0x00, 0x00,    //First column of the hyperlink
+                     0x00, 0x00,    //Last column of the hyperlink
+
+                     //16-byte GUID. Seems to be always the same. Does not depend on the hyperlink type
+                     (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
+                     (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
+
+                    0x02, 0x00, 0x00, 0x00, //integer, always 2
+
+                    // flags. Define the type of the hyperlink:
+                    // HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL
+                    0x17, 0x00, 0x00, 0x00,
+
+                    0x08, 0x00, 0x00, 0x00, //length of the label including the trailing '\0'
+
+                    //label:
+                    0x4D, 0x00, 0x79, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x6B, 0x00, 0x00, 0x00,
+
+                    //16-byte link moniker: HyperlinkRecord.URL_MONIKER
+                    (byte)0xE0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE,  0x11,
+                    (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
+
+                    //count of bytes in the address including the tail
+                    0x48, 0x00, 0x00, 0x00, //integer
+
+                    //the actual link, terminated by '\u0000'
+                    0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x3A, 0x00, 0x2F, 0x00,
+                    0x2F, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x2E, 0x00, 0x6C, 0x00,
+                    0x61, 0x00, 0x6B, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x73, 0x00,
+                    0x2E, 0x00, 0x63, 0x00, 0x6F, 0x00, 0x6D, 0x00, 0x2F, 0x00, 0x00, 0x00,
+
+                    //standard 24-byte tail of a URL link. Seems to always be the same for all URL HLINKs
+                    0x79, 0x58, (byte)0x81, (byte)0xF4, 0x3B, 0x1D, 0x7F, 0x48, (byte)0xAF, 0x2C,
+                    (byte)0x82, 0x5D, (byte)0xC4, (byte)0x85, 0x27, 0x63, 0x00, 0x00, 0x00,
+                    0x00, (byte)0xA5, (byte)0xAB, 0x00, 0x00};
+
+    //link to a file in the current directory: link1.xls
+    byte[] data2 =  {0x00, 0x00,
+                     0x00, 0x00,
+                     0x00, 0x00,
+                     0x00, 0x00,
+                     //16-bit GUID. Seems to be always the same. Does not depend on the hyperlink type
+                     (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
+                     (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
+
+                     0x02, 0x00, 0x00, 0x00,    //integer, always 2
+
+                     0x15, 0x00, 0x00, 0x00,    //options: HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_LABEL
+
+                     0x05, 0x00, 0x00, 0x00,    //length of the label
+                     //label
+                     0x66, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x00, 0x00,
+
+                     //16-byte link moniker: HyperlinkRecord.FILE_MONIKER
+                     0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+
+                     0x00, 0x00,    //level
+                     0x0A, 0x00, 0x00, 0x00,    //length of the path )
+
+                     //path to the file (plain ISO-8859 bytes, NOT UTF-16LE!)
+                     0x6C, 0x69, 0x6E, 0x6B, 0x31, 0x2E, 0x78, 0x6C, 0x73, 0x00,
+
+                     //standard 28-byte tail of a file link
+                     (byte)0xFF, (byte)0xFF, (byte)0xAD, (byte)0xDE, 0x00, 0x00, 0x00, 0x00,
+                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+    // mailto:ebgans@mail.ru?subject=Hello,%20Ebgans!
+    byte[] data3 = {0x01, 0x00,
+                    0x01, 0x00,
+                    0x00, 0x00,
+                    0x00, 0x00,
+
+                    //16-bit GUID. Seems to be always the same. Does not depend on the hyperlink type
+                    (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
+                    (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
+
+                    0x02, 0x00, 0x00, 0x00, //integer, always 2
+
+                    0x17, 0x00, 0x00, 0x00,  //options: HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL
+
+                    0x06, 0x00, 0x00, 0x00,     //length of the label
+                    0x65, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x00, 0x00, //label
+
+                    //16-byte link moniker: HyperlinkRecord.URL_MONIKER
+                    (byte)0xE0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
+                    (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
+
+                    //length of the address including the tail.
+                    0x76, 0x00, 0x00, 0x00,
+
+                    //the address is terminated by '\u0000'
+                    0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x74, 0x00, 0x6F, 0x00,
+                    0x3A, 0x00, 0x65, 0x00, 0x62, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6E, 0x00,
+                    0x73, 0x00, 0x40, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6C, 0x00,
+                    0x2E, 0x00, 0x72, 0x00, 0x75, 0x00, 0x3F, 0x00, 0x73, 0x00, 0x75, 0x00,
+                    0x62, 0x00, 0x6A, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3D, 0x00,
+                    0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x2C, 0x00,
+                    0x25, 0x00, 0x32, 0x00, 0x30, 0x00, 0x45, 0x00, 0x62, 0x00, 0x67, 0x00,
+                    0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, 0x21, 0x00, 0x00, 0x00,
+
+                    //standard 24-byte tail of a URL link
+                    0x79, 0x58, (byte)0x81, (byte)0xF4, 0x3B, 0x1D, 0x7F, 0x48, (byte)0xAF, (byte)0x2C,
+                    (byte)0x82, 0x5D, (byte)0xC4, (byte)0x85, 0x27, 0x63, 0x00, 0x00, 0x00,
+                    0x00, (byte)0xA5, (byte)0xAB, 0x00, 0x00
+    };
+
+    //link to a place in worksheet: Sheet1!A1
+    byte[] data4 = {0x03, 0x00,
+                    0x03, 0x00,
+                    0x00, 0x00,
+                    0x00, 0x00,
+
+                    //16-bit GUID. Seems to be always the same. Does not depend on the hyperlink type
+                    (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
+                    (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
+
+                    0x02, 0x00, 0x00, 0x00, //integer, always 2
+
+                    0x1C, 0x00, 0x00, 0x00, //flags: HyperlinkRecord.HLINK_LABEL | HyperlinkRecord.HLINK_PLACE
+
+                    0x06, 0x00, 0x00, 0x00, //length of the label
+
+                    0x70, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x00, 0x00, //label
+
+                    0x0A, 0x00, 0x00, 0x00, //length of the document link including trailing zero
+
+                    //link: Sheet1!A1
+                    0x53, 0x00, 0x68, 0x00, 0x65, 0x00, 0x65, 0x00, 0x74, 0x00, 0x31, 0x00, 0x21,
+                    0x00, 0x41, 0x00, 0x31, 0x00, 0x00, 0x00};
+
+    public void testReadURLLink(){
+        RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data1.length, data1);
+        HyperlinkRecord link = new HyperlinkRecord(is);
+        assertEquals(2, link.getFirstRow());
+        assertEquals(2, link.getLastRow());
+        assertEquals(0, link.getFirstColumn());
+        assertEquals(0, link.getLastColumn());
+        assertTrue(Arrays.equals(HyperlinkRecord.STD_MONIKER, link.getGuid()));
+        assertTrue(Arrays.equals(HyperlinkRecord.URL_MONIKER, link.getMoniker()));
+        assertEquals(2, link.getLabelOptions());
+        int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL;
+        assertEquals(0x17, opts);
+        assertEquals(opts, link.getLinkOptions());
+        assertEquals(0, link.getFileOptions());
+
+        assertEquals("My Link", link.getLabel());
+        assertEquals("http://www.lakings.com/", link.getAddress());
+    }
+
+    public void testReadFileLink(){
+        RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data2.length, data2);
+        HyperlinkRecord link = new HyperlinkRecord(is);
+        assertEquals(0, link.getFirstRow());
+        assertEquals(0, link.getLastRow());
+        assertEquals(0, link.getFirstColumn());
+        assertEquals(0, link.getLastColumn());
+        assertTrue(Arrays.equals(HyperlinkRecord.STD_MONIKER, link.getGuid()));
+        assertTrue(Arrays.equals(HyperlinkRecord.FILE_MONIKER, link.getMoniker()));
+        assertEquals(2, link.getLabelOptions());
+        int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_LABEL;
+        assertEquals(0x15, opts);
+        assertEquals(opts, link.getLinkOptions());
+
+        assertEquals("file", link.getLabel());
+        assertEquals("link1.xls", link.getAddress());
+    }
+
+    public void testReadEmailLink(){
+        RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data3.length, data3);
+        HyperlinkRecord link = new HyperlinkRecord(is);
+        assertEquals(1, link.getFirstRow());
+        assertEquals(1, link.getLastRow());
+        assertEquals(0, link.getFirstColumn());
+        assertEquals(0, link.getLastColumn());
+        assertTrue(Arrays.equals(HyperlinkRecord.STD_MONIKER, link.getGuid()));
+        assertTrue(Arrays.equals(HyperlinkRecord.URL_MONIKER, link.getMoniker()));
+        assertEquals(2, link.getLabelOptions());
+        int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL;
+        assertEquals(0x17, opts);
+        assertEquals(opts, link.getLinkOptions());
+
+        assertEquals("email", link.getLabel());
+        assertEquals("mailto:ebgans@mail.ru?subject=Hello,%20Ebgans!", link.getAddress());
+    }
+
+    public void testReadDocumentLink(){
+        RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data4.length, data4);
+        HyperlinkRecord link = new HyperlinkRecord(is);
+        assertEquals(3, link.getFirstRow());
+        assertEquals(3, link.getLastRow());
+        assertEquals(0, link.getFirstColumn());
+        assertEquals(0, link.getLastColumn());
+        assertTrue(Arrays.equals(HyperlinkRecord.STD_MONIKER, link.getGuid()));
+        assertEquals(2, link.getLabelOptions());
+        int opts = HyperlinkRecord.HLINK_LABEL | HyperlinkRecord.HLINK_PLACE;
+        assertEquals(0x1C, opts);
+        assertEquals(opts, link.getLinkOptions());
+
+        assertEquals("place", link.getLabel());
+        assertEquals("Sheet1!A1", link.getAddress());
+    }
+
+    private void serialize(byte[] data){
+        RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data.length, data);
+        HyperlinkRecord link = new HyperlinkRecord(is);
+        byte[] bytes1 = link.serialize();
+        is = new RecordInputStream(new ByteArrayInputStream(bytes1));
+        is.nextRecord();
+        link = new HyperlinkRecord(is);
+        byte[] bytes2 = link.serialize();
+        assertEquals(bytes1.length, bytes2.length);
+        assertTrue(Arrays.equals(bytes1, bytes2));
+    }
+
+    public void testSerialize(){
+        serialize(data1);
+        serialize(data2);
+        serialize(data3);
+        serialize(data4);
+    }
+
+    public void testCreateURLRecord() throws Exception {
+        HyperlinkRecord link = new HyperlinkRecord();
+        link.newUrlLink();
+        link.setFirstRow((short)2);
+        link.setLastRow((short)2);
+        link.setLabel("My Link");
+        link.setAddress("http://www.lakings.com/");
+
+        byte[] tmp = link.serialize();
+        byte[] ser = new byte[tmp.length-4];
+        System.arraycopy(tmp, 4, ser, 0, ser.length);
+        assertEquals(data1.length, ser.length);
+        assertTrue(Arrays.equals(data1, ser));
+    }
+
+    public void testCreateFileRecord() throws Exception {
+        HyperlinkRecord link = new HyperlinkRecord();
+        link.newFileLink();
+        link.setFirstRow((short)0);
+        link.setLastRow((short)0);
+        link.setLabel("file");
+        link.setAddress("link1.xls");
+
+        byte[] tmp = link.serialize();
+        byte[] ser = new byte[tmp.length-4];
+        System.arraycopy(tmp, 4, ser, 0, ser.length);
+        assertEquals(data2.length, ser.length);
+        assertTrue(Arrays.equals(data2, ser));
+    }
+
+    public void testCreateDocumentRecord() throws Exception {
+        HyperlinkRecord link = new HyperlinkRecord();
+        link.newDocumentLink();
+        link.setFirstRow((short)3);
+        link.setLastRow((short)3);
+        link.setLabel("place");
+        link.setAddress("Sheet1!A1");
+
+        byte[] tmp = link.serialize();
+        byte[] ser = new byte[tmp.length-4];
+        System.arraycopy(tmp, 4, ser, 0, ser.length);
+        assertEquals(data4.length, ser.length);
+        assertTrue(Arrays.equals(data4, ser));
+    }
+
+    public void testCreateEmailtRecord() throws Exception {
+        HyperlinkRecord link = new HyperlinkRecord();
+        link.newUrlLink();
+        link.setFirstRow((short)1);
+        link.setLastRow((short)1);
+        link.setLabel("email");
+        link.setAddress("mailto:ebgans@mail.ru?subject=Hello,%20Ebgans!");
+
+        byte[] tmp = link.serialize();
+        byte[] ser = new byte[tmp.length-4];
+        System.arraycopy(tmp, 4, ser, 0, ser.length);
+        assertEquals(data3.length, ser.length);
+        assertTrue(Arrays.equals(data3, ser));
+    }
+
+    public void testClone() throws Exception {
+        byte[][] data = {data1, data2, data3, data4};
+        for (int i = 0; i < data.length; i++) {
+            RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data[i].length, data[i]);
+            HyperlinkRecord link = new HyperlinkRecord(is);
+            HyperlinkRecord clone = (HyperlinkRecord)link.clone();
+            assertTrue(Arrays.equals(link.serialize(), clone.serialize()));
         }
-	}
 
-	public void testSecondRecord() throws Exception {
-        RecordInputStream inp = new RecordInputStream(
-                new ByteArrayInputStream(data2)
-        );
-        inp.nextRecord();
-
-        HyperlinkRecord r = new HyperlinkRecord(inp);
-        
-        assertEquals(2, r.getRow());
-        assertEquals(4, r.getColumn());
-        assertEquals(4, r.getXFIndex());
-        
-		assertEquals("Stacie@ABC.com", r.getLabel());
-		assertEquals("mailto:Stacie@ABC.com", r.getUrlString());
-	}
+    }
 }

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java?rev=619310&r1=619309&r2=619310&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java Thu Feb  7 00:56:59 2008
@@ -320,8 +320,8 @@
 
         assertEquals("Foo", link.getLabel());
         assertEquals("http://poi.apache.org/", link.getAddress());
-        assertEquals(4, link.getRow());
-        assertEquals(0, link.getColumn());
+        assertEquals(4, link.getFirstRow());
+        assertEquals(0, link.getFirstColumn());
     }
     
     /**
@@ -339,16 +339,16 @@
         assertNotNull(link1);
         assertEquals("Foo", link1.getLabel());
         assertEquals("http://poi.apache.org/", link1.getAddress());
-        assertEquals(4, link1.getRow());
-        assertEquals(0, link1.getColumn());
+        assertEquals(4, link1.getFirstRow());
+        assertEquals(0, link1.getFirstColumn());
 
         HSSFCell cell2 = sheet.getRow(8).getCell((short)1);
         HSSFHyperlink link2 = cell2.getHyperlink();
         assertNotNull(link2);
         assertEquals("Bar", link2.getLabel());
-        assertEquals("http://poi.apache.org/", link2.getAddress());
-        assertEquals(8, link2.getRow());
-        assertEquals(1, link2.getColumn());
+        assertEquals("http://poi.apache.org/hssf/", link2.getAddress());
+        assertEquals(8, link2.getFirstRow());
+        assertEquals(1, link2.getFirstColumn());
 
     }
     

Added: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java?rev=619310&view=auto
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java (added)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java Thu Feb  7 00:56:59 2008
@@ -0,0 +1,191 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+package org.apache.poi.hssf.usermodel;
+
+import junit.framework.TestCase;
+
+import java.io.*;
+
+/**
+ * Tests HSSFHyperlink.
+ *
+ * @author  Yegor Kozlov
+ */
+public class TestHSSFHyperlink extends TestCase {
+    protected String cwd = System.getProperty("HSSF.testdata.path");
+
+    /**
+     * Test that we can read hyperlinks.
+     */
+    public void testRead() throws Exception {
+
+        FileInputStream is = new FileInputStream(new File(cwd, "HyperlinksOnManySheets.xls"));
+        HSSFWorkbook wb = new HSSFWorkbook(is);
+        is.close();
+
+        HSSFSheet sheet;
+        HSSFCell cell;
+        HSSFHyperlink link;
+
+        sheet = wb.getSheet("WebLinks");
+        cell = sheet.getRow(4).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("POI", link.getLabel());
+        assertEquals("POI", cell.getRichStringCellValue().getString());
+        assertEquals("http://poi.apache.org/", link.getAddress());
+
+        cell = sheet.getRow(8).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("HSSF", link.getLabel());
+        assertEquals("HSSF", cell.getRichStringCellValue().getString());
+        assertEquals("http://poi.apache.org/hssf/", link.getAddress());
+
+        sheet = wb.getSheet("Emails");
+        cell = sheet.getRow(4).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("dev", link.getLabel());
+        assertEquals("dev", cell.getRichStringCellValue().getString());
+        assertEquals("mailto:dev@poi.apache.org", link.getAddress());
+
+        sheet = wb.getSheet("Internal");
+        cell = sheet.getRow(4).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("Link To First Sheet", link.getLabel());
+        assertEquals("Link To First Sheet", cell.getRichStringCellValue().getString());
+        assertEquals("WebLinks!A1", link.getAddress());
+    }
+
+    public void testModify() throws Exception {
+        FileInputStream is = new FileInputStream(new File(cwd, "HyperlinksOnManySheets.xls"));
+        HSSFWorkbook wb = new HSSFWorkbook(is);
+        is.close();
+
+        HSSFSheet sheet;
+        HSSFCell cell;
+        HSSFHyperlink link;
+
+        sheet = wb.getSheet("WebLinks");
+        cell = sheet.getRow(4).getCell((short)0);
+        link = cell.getHyperlink();
+        //modify the link
+        link.setAddress("www.apache.org");
+
+        //serialize and read again
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        wb.write(out);
+
+        wb = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
+        sheet = wb.getSheet("WebLinks");
+        cell = sheet.getRow(4).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("www.apache.org", link.getAddress());
+
+    }
+
+    public void testCreate() throws Exception {
+        HSSFWorkbook wb = new HSSFWorkbook();
+
+        HSSFCell cell;
+        HSSFSheet sheet = wb.createSheet("Hyperlinks");
+
+        //URL
+        cell = sheet.createRow(0).createCell((short)0);
+        cell.setCellValue("URL Link");
+        HSSFHyperlink link = new HSSFHyperlink(HSSFHyperlink.LINK_URL);
+        link.setAddress("http://poi.apache.org/");
+        cell.setHyperlink(link);
+
+        //link to a file in the current directory
+        cell = sheet.createRow(1).createCell((short)0);
+        cell.setCellValue("File Link");
+        link = new HSSFHyperlink(HSSFHyperlink.LINK_FILE);
+        link.setAddress("link1.xls");
+        cell.setHyperlink(link);
+
+        //e-mail link
+        cell = sheet.createRow(2).createCell((short)0);
+        cell.setCellValue("Email Link");
+        link = new HSSFHyperlink(HSSFHyperlink.LINK_EMAIL);
+        //note, if subject contains white spaces, make sure they are url-encoded
+        link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
+        cell.setHyperlink(link);
+
+        //link to a place in this workbook
+
+        //create a target sheet and cell
+        HSSFSheet sheet2 = wb.createSheet("Target Sheet");
+        sheet2.createRow(0).createCell((short)0).setCellValue("Target Cell");
+
+        cell = sheet.createRow(3).createCell((short)0);
+        cell.setCellValue("Worksheet Link");
+        link = new HSSFHyperlink(HSSFHyperlink.LINK_DOCUMENT);
+        link.setAddress("'Target Sheet'!A1");
+        cell.setHyperlink(link);
+
+        //serialize and read again
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        wb.write(out);
+
+        wb = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
+        sheet = wb.getSheet("Hyperlinks");
+        cell = sheet.getRow(0).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("http://poi.apache.org/", link.getAddress());
+
+        cell = sheet.getRow(1).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("link1.xls", link.getAddress());
+
+        cell = sheet.getRow(2).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("mailto:poi@apache.org?subject=Hyperlinks", link.getAddress());
+
+        cell = sheet.getRow(3).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("'Target Sheet'!A1", link.getAddress());
+    }
+
+    public void testCloneSheet() throws Exception {
+        FileInputStream is = new FileInputStream(new File(cwd, "HyperlinksOnManySheets.xls"));
+        HSSFWorkbook wb = new HSSFWorkbook(is);
+        is.close();
+
+        HSSFCell cell;
+        HSSFHyperlink link;
+
+        HSSFSheet sheet = wb.cloneSheet(0);
+
+        cell = sheet.getRow(4).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("http://poi.apache.org/", link.getAddress());
+
+        cell = sheet.getRow(8).getCell((short)0);
+        link = cell.getHyperlink();
+        assertNotNull(link);
+        assertEquals("http://poi.apache.org/hssf/", link.getAddress());
+    }
+}

Propchange: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java
------------------------------------------------------------------------------
    svn:executable = *



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org