From 4a1c6abf5951271392dd431f555e8e24e0124b8e Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Sat, 5 Apr 2008 21:43:53 +0000 Subject: [PATCH] More work on XSSF Hyperlinks. Still not quite there, but mostly now. Just need to fix a openxml4j bug first though git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@645179 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/usermodel/HSSFCell.java | 5 +- .../hssf/usermodel/HSSFCreationHelper.java | 3 - .../poi/hssf/usermodel/HSSFHyperlink.java | 12 +- .../org/apache/poi/ss/usermodel/Cell.java | 3 + .../apache/poi/ss/usermodel/CellStyle.java | 5 +- .../org/apache/poi/ss/usermodel/Cell.java | 14 ++- .../poi/ss/usermodel/CreationHelper.java | 5 +- .../apache/poi/ss/usermodel/Hyperlink.java | 8 +- .../apache/poi/xssf/usermodel/XSSFCell.java | 8 ++ .../xssf/usermodel/XSSFCreationHelper.java | 5 +- .../poi/xssf/usermodel/XSSFHyperlink.java | 109 ++++++++++++------ .../apache/poi/xssf/usermodel/XSSFSheet.java | 69 ++++++++++- .../poi/xssf/usermodel/XSSFWorkbook.java | 10 +- .../poi/xssf/usermodel/TestXSSFHyperlink.java | 86 ++++++++++++++ 14 files changed, 280 insertions(+), 62 deletions(-) create mode 100644 src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index ededf0d648..2a605c8a75 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -40,6 +40,7 @@ import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.RichTextString; /** @@ -1120,7 +1121,9 @@ public class HSSFCell implements Cell * * @param link hypelrink associated with this cell */ - public void setHyperlink(HSSFHyperlink link){ + public void setHyperlink(Hyperlink hyperlink){ + HSSFHyperlink link = (HSSFHyperlink)hyperlink; + link.setFirstRow(record.getRow()); link.setLastRow(record.getRow()); link.setFirstColumn(record.getColumn()); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCreationHelper.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCreationHelper.java index 42d28a7281..6986ef94b5 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCreationHelper.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCreationHelper.java @@ -41,9 +41,6 @@ public class HSSFCreationHelper implements CreationHelper { return dataFormat; } - public HSSFHyperlink createHyperlink(int type, Sheet sheetFor) { - return createHyperlink(type); - } public HSSFHyperlink createHyperlink(int type) { return new HSSFHyperlink(type); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java b/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java index 53d9298ee0..3bfbf880b3 100755 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java @@ -130,7 +130,7 @@ public class HSSFHyperlink implements Hyperlink { * * @return the 0-based column of the first cell that contains the hyperlink */ - public short getFirstColumn(){ + public int getFirstColumn(){ return record.getFirstColumn(); } @@ -139,8 +139,8 @@ public class HSSFHyperlink implements Hyperlink { * * @param col the 0-based column of the first cell that contains the hyperlink */ - public void setFirstColumn(short col){ - record.setFirstColumn(col); + public void setFirstColumn(int col){ + record.setFirstColumn((short)col); } /** @@ -148,7 +148,7 @@ public class HSSFHyperlink implements Hyperlink { * * @return the 0-based column of the last cell that contains the hyperlink */ - public short getLastColumn(){ + public int getLastColumn(){ return record.getLastColumn(); } @@ -157,8 +157,8 @@ public class HSSFHyperlink implements Hyperlink { * * @param col the 0-based column of the last cell that contains the hyperlink */ - public void setLastColumn(short col){ - record.setLastColumn(col); + public void setLastColumn(int col){ + record.setLastColumn((short)col); } /** diff --git a/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Cell.java b/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Cell.java index 28b8b14ea2..bdee648b75 100644 --- a/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Cell.java +++ b/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Cell.java @@ -17,6 +17,7 @@ package org.apache.poi.ss.usermodel; +import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFRichTextString; /** @@ -80,6 +81,8 @@ public interface Cell { byte getErrorCellValue(); String getCellFormula(); + HSSFCellStyle getCellStyle(); + boolean getBooleanCellValue(); double getNumericCellValue(); HSSFRichTextString getRichStringCellValue(); diff --git a/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/CellStyle.java b/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/CellStyle.java index c23d696aef..2105937fe8 100644 --- a/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/CellStyle.java +++ b/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/CellStyle.java @@ -17,4 +17,7 @@ package org.apache.poi.ss.usermodel; -public interface CellStyle {} +public interface CellStyle { + short getDataFormat(); + String getDataFormatString(); +} diff --git a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Cell.java b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Cell.java index 1a250b26d8..b63f604657 100644 --- a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Cell.java +++ b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Cell.java @@ -20,7 +20,6 @@ package org.apache.poi.ss.usermodel; import java.util.Calendar; import java.util.Date; - public interface Cell { /** @@ -281,4 +280,17 @@ public interface Cell { */ Comment getCellComment(); + /** + * Returns hyperlink associated with this cell + * + * @return hyperlink associated with this cell or null if not found + */ + public Hyperlink getHyperlink(); + + /** + * Assign a hypelrink to this cell + * + * @param link hypelrink associated with this cell + */ + public void setHyperlink(Hyperlink link); } \ No newline at end of file diff --git a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/CreationHelper.java b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/CreationHelper.java index 375429c6b9..f0b119f99a 100644 --- a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/CreationHelper.java +++ b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/CreationHelper.java @@ -41,8 +41,7 @@ public interface CreationHelper { DataFormat createDataFormat(); /** - * Creates a new Hyperlink, of the given type, - * for the given sheet + * Creates a new Hyperlink, of the given type */ - Hyperlink createHyperlink(int type, Sheet sheetFor); + Hyperlink createHyperlink(int type); } \ No newline at end of file diff --git a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Hyperlink.java b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Hyperlink.java index c207c925ad..4fbacf338f 100644 --- a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Hyperlink.java +++ b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Hyperlink.java @@ -73,28 +73,28 @@ public interface Hyperlink { * * @return the 0-based column of the first cell that contains the hyperlink */ - public short getFirstColumn(); + public int getFirstColumn(); /** * 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 void setFirstColumn(short col); + public void setFirstColumn(int col); /** * Return 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(); + public int getLastColumn(); /** * 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 void setLastColumn(short col); + public void setLastColumn(int col); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java index 31c764eb3d..3606415b8f 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -24,6 +24,7 @@ import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.SharedStringSource; import org.apache.poi.ss.usermodel.StylesSource; @@ -398,4 +399,11 @@ public class XSSFCell implements Cell { public RichTextString createRichTextString(String text) { return new XSSFRichTextString(text); } + + public Hyperlink getHyperlink() { + return row.getSheet().getHyperlink(row.getRowNum(), cellNum); + } + public void setHyperlink(Hyperlink hyperlink) { + row.getSheet().setCellHyperlink((XSSFHyperlink)hyperlink); + } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java index e22fe01fa0..771f68482f 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java @@ -20,7 +20,6 @@ import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.RichTextString; -import org.apache.poi.ss.usermodel.Sheet; public class XSSFCreationHelper implements CreationHelper { private XSSFWorkbook workbook; @@ -43,7 +42,7 @@ public class XSSFCreationHelper implements CreationHelper { return dataFormat; } - public Hyperlink createHyperlink(int type, Sheet sheetFor) { - return new XSSFHyperlink(type, (XSSFSheet)sheetFor); + public Hyperlink createHyperlink(int type) { + return new XSSFHyperlink(type); } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java index feba0cf9df..2a27138a75 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java @@ -16,11 +16,16 @@ ==================================================================== */ package org.apache.poi.xssf.usermodel; +import java.net.URI; + import org.apache.poi.ss.usermodel.Hyperlink; +import org.apache.poi.ss.util.CellReference; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink; import org.openxml4j.opc.Package; import org.openxml4j.opc.PackagePart; +import org.openxml4j.opc.PackageRelationship; + /** * XSSF Implementation of a Hyperlink. @@ -29,20 +34,39 @@ import org.openxml4j.opc.PackagePart; */ public class XSSFHyperlink implements Hyperlink { private int type; - private XSSFSheet sheet; + private PackageRelationship externalRel; private CTHyperlink ctHyperlink; + private String location; - protected XSSFHyperlink(int type, XSSFSheet sheet) { + protected XSSFHyperlink(int type) { this.type = type; - this.sheet = sheet; this.ctHyperlink = CTHyperlink.Factory.newInstance(); } - protected XSSFHyperlink(CTHyperlink ctHyperlink, XSSFSheet sheet) { - this.sheet = sheet; + protected XSSFHyperlink(CTHyperlink ctHyperlink, PackageRelationship hyperlinkRel) { this.ctHyperlink = ctHyperlink; + this.externalRel = hyperlinkRel; // Figure out the Hyperlink type - // TODO + + // If it has a location, it's internal + if(ctHyperlink.getLocation() != null) { + type = Hyperlink.LINK_DOCUMENT; + location = ctHyperlink.getLocation(); + } else { + // Otherwise it's somehow external, check + // the relation to see how + if(externalRel == null) { + if(ctHyperlink.getId() != null) { + throw new IllegalStateException("The hyperlink for cell " + ctHyperlink.getRef() + " references relation " + ctHyperlink.getId() + ", but that didn't exist!"); + } else { + throw new IllegalStateException("A sheet hyperlink must either have a location, or a relationship. Found:\n" + ctHyperlink); + } + } + // TODO + + //URI target = externalRel.getTargetURI(); + //location = target.toString(); + } } /** @@ -57,65 +81,80 @@ public class XSSFHyperlink implements Hyperlink { * this hyperlink? */ public boolean needsRelationToo() { - // TODO - return false; + return (type != Hyperlink.LINK_DOCUMENT); } /** * Generates the relation if required */ - protected void generateRelationIfNeeded(Package pkg, PackagePart sheetPart) { - // TODO + protected void generateRelationIfNeeded(PackagePart sheetPart) { + if(needsRelationToo()) { + // TODO + } } public int getType() { return type; } + /** + * Get the reference of the cell this applies to, + * eg A55 + */ + public String getCellRef() { + return ctHyperlink.getRef(); + } + public String getAddress() { - // TODO Auto-generated method stub - return null; + return location; } public String getLabel() { - // TODO Auto-generated method stub - return null; + return ctHyperlink.getDisplay(); } public void setLabel(String label) { - // TODO Auto-generated method stub + ctHyperlink.setDisplay(label); } public void setAddress(String address) { - // TODO Auto-generated method stub - + location = address; + } + + private CellReference buildCellReference() { + return new CellReference(ctHyperlink.getRef()); } - public short getFirstColumn() { - // TODO Auto-generated method stub - return 0; + public int getFirstColumn() { + return buildCellReference().getCol(); } - public int getFirstRow() { - // TODO Auto-generated method stub - return 0; + public int getLastColumn() { + return buildCellReference().getCol(); } - public short getLastColumn() { - // TODO Auto-generated method stub - return 0; + + public int getFirstRow() { + return buildCellReference().getRow(); } public int getLastRow() { - // TODO Auto-generated method stub - return 0; + return buildCellReference().getRow(); } - public void setFirstColumn(short col) { - // TODO Auto-generated method stub + public void setFirstColumn(int col) { + ctHyperlink.setRef( + new CellReference( + getFirstRow(), col + ).formatAsString() + ); } - public void setFirstRow(int row) { - // TODO Auto-generated method stub + public void setLastColumn(int col) { + setFirstColumn(col); } - public void setLastColumn(short col) { - // TODO Auto-generated method stub + public void setFirstRow(int row) { + ctHyperlink.setRef( + new CellReference( + row, getFirstColumn() + ).formatAsString() + ); } public void setLastRow(int row) { - // TODO Auto-generated method stub + setFirstRow(row); } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 78c9d4e983..d6106ff20e 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -30,6 +31,7 @@ import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.CommentsSource; import org.apache.poi.ss.usermodel.Footer; import org.apache.poi.ss.usermodel.Header; +import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.Patriarch; import org.apache.poi.ss.usermodel.PrintSetup; import org.apache.poi.ss.usermodel.Row; @@ -38,10 +40,14 @@ import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.model.CommentsTable; import org.apache.poi.xssf.usermodel.helpers.ColumnHelper; import org.apache.xmlbeans.XmlOptions; +import org.openxml4j.opc.PackagePart; +import org.openxml4j.opc.PackageRelationship; +import org.openxml4j.opc.PackageRelationshipCollection; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBreak; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDialogsheet; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageBreak; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageMargins; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageSetUpPr; @@ -62,6 +68,7 @@ public class XSSFSheet implements Sheet { protected CTWorksheet worksheet; protected CTDialogsheet dialogsheet; protected List rows; + protected List hyperlinks; protected ColumnHelper columnHelper; protected XSSFWorkbook workbook; protected CommentsSource sheetComments; @@ -90,10 +97,14 @@ public class XSSFSheet implements Sheet { } initRows(this.worksheet); initColumns(this.worksheet); + + hyperlinks = new ArrayList(); } public XSSFSheet(XSSFWorkbook workbook) { this.workbook = workbook; + + hyperlinks = new ArrayList(); } public XSSFWorkbook getWorkbook() { @@ -105,7 +116,7 @@ public class XSSFSheet implements Sheet { * will accept without a massive huff, and write into * the OutputStream supplied. */ - protected void save(OutputStream out, XmlOptions xmlOptions) throws IOException { + protected void save(PackagePart sheetPart, XmlOptions xmlOptions) throws IOException { // Excel objects to if(worksheet.getColsArray().length == 1) { CTCols col = worksheet.getColsArray(0); @@ -113,9 +124,28 @@ public class XSSFSheet implements Sheet { worksheet.setColsArray(null); } } + + // Now re-generate our CTHyperlinks, if needed + if(hyperlinks.size() > 0) { + if(worksheet.getHyperlinks() == null) { + worksheet.addNewHyperlinks(); + } + CTHyperlink[] ctHls = new CTHyperlink[hyperlinks.size()]; + for(int i=0; i