aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/poi/hssf/record/HyperlinkRecord.java662
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFCell.java21
-rwxr-xr-xsrc/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java137
3 files changed, 549 insertions, 271 deletions
diff --git a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java
index 0dcd45a724..798d4e1ff5 100644
--- a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java
+++ b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java
@@ -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 @@ import org.apache.poi.util.StringUtil;
* 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 };
+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.
- /** Indicates the STD_LINK in the Record */
- // MHM: to be added when necessary
- private static byte[] GUID_OF_STD_LINK = {};
- /** Logger */
- public static final Log log = LogFactory.getLog(HyperlinkRecord.class);
+ 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};
- // quick and dirty
- private static final boolean _DEBUG_ = true;
+ /**
+ * 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;
-
- /** Blank Constructor */
+ /**
+ * First row of the hyperlink
+ */
+ private int rwFirst;
+
+ /**
+ * Last row of the hyperlink
+ */
+ private int rwLast;
+
+ /**
+ * First column of the hyperlink
+ */
+ private short colFirst;
+
+ /**
+ * 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)
{
- return field_2_row;
+ this.colFirst = col;
}
- /* (non-Javadoc)
- * @see org.apache.poi.hssf.record.CellValueRecordInterface#getXFIndex()
+ /**
+ * 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 colLast;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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 rwLast;
+ }
+
+ /**
+ * 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)
+ {
+ this.rwLast = row;
}
- /* (non-Javadoc)
- * @see org.apache.poi.hssf.record.CellValueRecordInterface#isEqual(org.apache.poi.hssf.record.CellValueRecordInterface)
+ /**
+ * Returns a 16-byte guid identifier. Seems to always equal {@link STD_MONIKER}
+ *
+ * @return 16-byte guid identifier
*/
- public boolean isEqual(CellValueRecordInterface i)
+ public byte[] getGuid()
{
- return ((this.getRow() == i.getRow()) && (this.getColumn() == i.getColumn()));
+ return guid;
}
- /* (non-Javadoc)
- * @see org.apache.poi.hssf.record.CellValueRecordInterface#setColumn(short)
+ /**
+ * Returns a 16-byte moniker.
+ *
+ * @return 16-byte moniker
*/
- public void setColumn(short col)
+ public byte[] getMoniker()
{
- this.field_3_column = col;
+ 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);
}
- /* (non-Javadoc)
- * @see org.apache.poi.hssf.record.CellValueRecordInterface#setRow(int)
+ /**
+ * Sets text label for this hyperlink
+ *
+ * @param label text label for this hyperlink
*/
- public void setRow(int row)
+ public void setLabel(String label)
{
- this.field_2_row = row;
+ 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 @@ public class HyperlinkRecord extends Record implements CellValueRecordInterface
*/
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 class HyperlinkRecord extends Record implements CellValueRecordInterface
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 @@ public class HyperlinkRecord extends Record implements CellValueRecordInterface
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[]{};
}
- /**
- * @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 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;
}
- public int getOptions(){
- return field_11_url_opts;
- }
+
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
index 7b6102b69d..646efe3103 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
@@ -1066,7 +1066,7 @@ public class HSSFCell
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 @@ public class HSSFCell
* @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 );
}
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java b/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java
index e1bd28af6c..7f1c2639c9 100755
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java
@@ -27,9 +27,9 @@ import java.util.List;
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 class HSSFHyperlink {
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 @@ public class HSSFHyperlink {
}
/**
+ * 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;
}
}