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
This commit is contained in:
Nick Burch 2008-04-05 21:43:53 +00:00
parent 72ef8c39c0
commit b021ef1561
14 changed files with 280 additions and 62 deletions

View File

@ -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());

View File

@ -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);
}

View File

@ -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);
}
/**

View File

@ -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();

View File

@ -17,4 +17,7 @@
package org.apache.poi.ss.usermodel;
public interface CellStyle {}
public interface CellStyle {
short getDataFormat();
String getDataFormatString();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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 getLastColumn() {
return buildCellReference().getCol();
}
public int getFirstRow() {
// TODO Auto-generated method stub
return 0;
}
public short getLastColumn() {
// TODO Auto-generated method stub
return 0;
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 setLastColumn(int col) {
setFirstColumn(col);
}
public void setFirstRow(int row) {
// TODO Auto-generated method stub
}
public void setLastColumn(short col) {
// TODO Auto-generated method stub
ctHyperlink.setRef(
new CellReference(
row, getFirstColumn()
).formatAsString()
);
}
public void setLastRow(int row) {
// TODO Auto-generated method stub
setFirstRow(row);
}
}

View File

@ -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<Row> rows;
protected List<XSSFHyperlink> 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<XSSFHyperlink>();
}
public XSSFSheet(XSSFWorkbook workbook) {
this.workbook = workbook;
hyperlinks = new ArrayList<XSSFHyperlink>();
}
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 <cols/>
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<ctHls.length; i++) {
// If our sheet has hyperlinks, have them add
// any relationships that they might need
XSSFHyperlink hyperlink = hyperlinks.get(i);
hyperlink.generateRelationIfNeeded(sheetPart);
// Now grab their underling object
ctHls[i] = hyperlink.getCTHyperlink();
}
worksheet.getHyperlinks().setHyperlinkArray(ctHls);
}
// Save
OutputStream out = sheetPart.getOutputStream();
worksheet.save(out, xmlOptions);
out.close();
}
protected CTWorksheet getWorksheet() {
@ -136,7 +166,24 @@ public class XSSFSheet implements Sheet {
protected void initColumns(CTWorksheet worksheet) {
columnHelper = new ColumnHelper(worksheet);
}
protected void initHyperlinks(PackageRelationshipCollection hyperRels) {
if(worksheet.getHyperlinks() == null) return;
// Turn each one into a XSSFHyperlink
for(CTHyperlink hyperlink : worksheet.getHyperlinks().getHyperlinkArray()) {
PackageRelationship hyperRel = null;
if(hyperlink.getId() != null) {
hyperRel = hyperRels.getRelationshipByID(hyperlink.getId());
}
// TODO: fix openxml4j
// hyperlinks.add(
// new XSSFHyperlink(hyperlink, hyperRel)
// );
}
}
protected CTSheet getSheet() {
return this.sheet;
}
@ -242,6 +289,16 @@ public class XSSFSheet implements Sheet {
public Comment getCellComment(int row, int column) {
return getComments().findCellComment(row, column);
}
public Hyperlink getHyperlink(int row, int column) {
String ref = new CellReference(row, column).formatAsString();
for(XSSFHyperlink hyperlink : hyperlinks) {
if(hyperlink.getCellRef().equals(ref)) {
return hyperlink;
}
}
return null;
}
public short[] getColumnBreaks() {
CTBreak[] brkArray = getSheetTypeColumnBreaks().getBrkArray();
@ -416,6 +473,10 @@ public class XSSFSheet implements Sheet {
// TODO Auto-generated method stub
return 0;
}
public int getNumHyperlinks() {
return hyperlinks.size();
}
public boolean getObjectProtect() {
// TODO Auto-generated method stub
@ -871,6 +932,10 @@ public class XSSFSheet implements Sheet {
getComments().setCellComment(cellRef, comment);
}
public void setCellHyperlink(XSSFHyperlink hyperlink) {
hyperlinks.add(hyperlink);
}
public String getActiveCell() {
return getSheetTypeSelection().getActiveCell();
}

View File

@ -281,6 +281,12 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
WorksheetDocument worksheetDoc = WorksheetDocument.Factory.parse(part.getInputStream());
XSSFSheet sheet = new XSSFSheet(ctSheet, worksheetDoc.getWorksheet(), this, comments);
this.sheets.add(sheet);
// Process external hyperlinks for the sheet,
// if there are any
PackageRelationshipCollection hyperlinkRels =
part.getRelationshipsByType(SHEET_HYPERLINKS.REL);
sheet.initHyperlinks(hyperlinkRels);
}
} catch (XmlException e) {
throw new IOException(e.toString());
@ -687,9 +693,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
// XXX This should not be needed, but apparently the setSaveOuter call above does not work in XMLBeans 2.2
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet"));
out = part.getOutputStream();
sheet.save(out, xmlOptions);
out.close();
sheet.save(part, xmlOptions);
// Update our internal reference for the package part
workbook.getSheets().getSheetArray(i).setId(rel.getId());

View File

@ -0,0 +1,86 @@
/* ====================================================================
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.xssf.usermodel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import junit.framework.TestCase;
import org.openxml4j.opc.Package;
public class TestXSSFHyperlink extends TestCase {
public TestXSSFHyperlink(String name) {
super(name);
// Use system out logger
System.setProperty(
"org.apache.poi.util.POILogger",
"org.apache.poi.util.SystemOutLogger"
);
}
public void testAddNew() throws Exception {
}
public void testLoadExisting() throws Exception {
File xml = new File(
System.getProperty("HSSF.testdata.path") +
File.separator + "WithMoreVariousData.xlsx"
);
assertTrue(xml.exists());
XSSFWorkbook workbook = new XSSFWorkbook(xml.toString());
assertEquals(3, workbook.getNumberOfSheets());
XSSFSheet sheet = (XSSFSheet)workbook.getSheetAt(0);
// TODO - check hyperlinks
//assertEquals(4, sheet.getNumHyperlinks());
}
public void testLoadSave() throws Exception {
File xml = new File(
System.getProperty("HSSF.testdata.path") +
File.separator + "WithMoreVariousData.xlsx"
);
assertTrue(xml.exists());
XSSFWorkbook workbook = new XSSFWorkbook(xml.toString());
assertEquals(3, workbook.getNumberOfSheets());
// TODO - check hyperlinks
// Write out, and check
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
// Load up again, check all links still there
XSSFWorkbook wb2 = new XSSFWorkbook(Package.open(bais));
assertEquals(3, wb2.getNumberOfSheets());
assertNotNull(wb2.getSheetAt(0));
assertNotNull(wb2.getSheetAt(1));
assertNotNull(wb2.getSheetAt(2));
// TODO
}
}