add support for reading hyperlinks that have cell refs that are area references (very limited update or write support as yet)

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1892141 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
PJ Fanning 2021-08-09 21:57:40 +00:00
parent 65d7486cc6
commit 7bcf6d5a6d
4 changed files with 106 additions and 33 deletions

View File

@ -22,7 +22,9 @@ import java.net.URISyntaxException;
import org.apache.poi.common.usermodel.HyperlinkType; import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink;
@ -264,20 +266,32 @@ public class XSSFHyperlink implements Hyperlink {
public void setCellReference(String ref) { public void setCellReference(String ref) {
_ctHyperlink.setRef(ref); _ctHyperlink.setRef(ref);
} }
@Internal @Internal
public void setCellReference(CellReference ref) { public void setCellReference(CellReference ref) {
setCellReference(ref.formatAsString()); setCellReference(ref.formatAsString());
} }
private CellReference buildCellReference() { private CellReference buildFirstCellReference() {
return buildCellReference(false);
}
private CellReference buildLastCellReference() {
return buildCellReference(true);
}
private CellReference buildCellReference(boolean lastCell) {
String ref = _ctHyperlink.getRef(); String ref = _ctHyperlink.getRef();
if (ref == null) { if (ref == null) {
ref = "A1"; ref = "A1";
} }
if (ref.contains(":")) {
AreaReference area = new AreaReference(ref, SpreadsheetVersion.EXCEL2007);
return lastCell ? area.getLastCell() : area.getFirstCell();
}
return new CellReference(ref); return new CellReference(ref);
} }
/** /**
* Return the column of the first cell that contains the hyperlink * Return the column of the first cell that contains the hyperlink
* *
@ -285,7 +299,7 @@ public class XSSFHyperlink implements Hyperlink {
*/ */
@Override @Override
public int getFirstColumn() { public int getFirstColumn() {
return buildCellReference().getCol(); return buildFirstCellReference().getCol();
} }
@ -296,7 +310,7 @@ public class XSSFHyperlink implements Hyperlink {
*/ */
@Override @Override
public int getLastColumn() { public int getLastColumn() {
return buildCellReference().getCol(); return buildLastCellReference().getCol();
} }
/** /**
@ -306,7 +320,7 @@ public class XSSFHyperlink implements Hyperlink {
*/ */
@Override @Override
public int getFirstRow() { public int getFirstRow() {
return buildCellReference().getRow(); return buildFirstCellReference().getRow();
} }
@ -317,7 +331,7 @@ public class XSSFHyperlink implements Hyperlink {
*/ */
@Override @Override
public int getLastRow() { public int getLastRow() {
return buildCellReference().getRow(); return buildLastCellReference().getRow();
} }
/** /**
@ -327,18 +341,19 @@ public class XSSFHyperlink implements Hyperlink {
*/ */
@Override @Override
public void setFirstColumn(int col) { public void setFirstColumn(int col) {
setCellReference(new CellReference( getFirstRow(), col )); String firstCellRef = CellReference.convertNumToColString(col) + (getFirstRow() + 1);
setCellRange(firstCellRef + ":" + buildLastCellReference().formatAsString());
} }
/** /**
* Set the column of the last cell that contains the hyperlink. * Set the column of the last cell that contains the hyperlink.
* For XSSF, a Hyperlink may only reference one cell
* *
* @param col the 0-based column of the last cell that contains the hyperlink * @param col the 0-based column of the last cell that contains the hyperlink
*/ */
@Override @Override
public void setLastColumn(int col) { public void setLastColumn(int col) {
setFirstColumn(col); String lastCellRef = CellReference.convertNumToColString(col) + (getLastRow() + 1);
setCellRange(buildFirstCellReference().formatAsString() + ":" + lastCellRef);
} }
/** /**
@ -348,18 +363,28 @@ public class XSSFHyperlink implements Hyperlink {
*/ */
@Override @Override
public void setFirstRow(int row) { public void setFirstRow(int row) {
setCellReference(new CellReference( row, getFirstColumn() )); String firstCellRef = CellReference.convertNumToColString(getFirstColumn()) + (row + 1);
setCellRange(firstCellRef + ":" + buildLastCellReference().formatAsString());
} }
/** /**
* Set the row of the last cell that contains the hyperlink. * Set the row of the last cell that contains the hyperlink.
* For XSSF, a Hyperlink may only reference one cell
* *
* @param row the 0-based row of the last cell that contains the hyperlink * @param row the 0-based row of the last cell that contains the hyperlink
*/ */
@Override @Override
public void setLastRow(int row) { public void setLastRow(int row) {
setFirstRow(row); String lastCellRef = CellReference.convertNumToColString(getLastColumn()) + (row + 1);
setCellRange(buildFirstCellReference().formatAsString() + ":" + lastCellRef);
}
private void setCellRange(String range) {
AreaReference ref = new AreaReference(range, SpreadsheetVersion.EXCEL2007);
if(ref.isSingleCell()) {
setCellReference(ref.getFirstCell());
} else {
setCellReference(ref.formatAsString());
}
} }
/** /**

View File

@ -55,23 +55,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.formula.FormulaShifter;
import org.apache.poi.ss.formula.SheetNameFormatter; import org.apache.poi.ss.formula.SheetNameFormatter;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.ss.usermodel.CellRange;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Footer;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Header;
import org.apache.poi.ss.usermodel.IgnoredErrorType;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Table;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellAddress; import org.apache.poi.ss.util.CellAddress;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
@ -846,9 +830,9 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
*/ */
@Override @Override
public XSSFHyperlink getHyperlink(CellAddress addr) { public XSSFHyperlink getHyperlink(CellAddress addr) {
String ref = addr.formatAsString(); for (XSSFHyperlink hyperlink : getHyperlinkList()) {
for(XSSFHyperlink hyperlink : hyperlinks) { if (addr.getRow() >= hyperlink.getFirstRow() && addr.getRow() <= hyperlink.getLastRow()
if(hyperlink.getCellRef().equals(ref)) { && addr.getColumn() >= hyperlink.getFirstColumn() && addr.getColumn() <= hyperlink.getLastColumn()) {
return hyperlink; return hyperlink;
} }
} }

View File

@ -51,6 +51,27 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
} }
} }
@Test
public void readSharedHyperlink() throws IOException {
try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("sharedhyperlink.xlsx")) {
XSSFSheet sheet = wb.getSheetAt(0);
XSSFHyperlink hyperlink3 = sheet.getHyperlink(new CellAddress("A3"));
XSSFHyperlink hyperlink4 = sheet.getHyperlink(new CellAddress("A4"));
XSSFHyperlink hyperlink5 = sheet.getHyperlink(new CellAddress("A5"));
assertNotNull(hyperlink3, "hyperlink found?");
assertEquals(hyperlink3, hyperlink4);
assertEquals(hyperlink3, hyperlink5);
assertEquals("A3:A5", hyperlink3.getCellRef());
assertEquals(0, hyperlink3.getFirstColumn());
assertEquals(0, hyperlink3.getLastColumn());
assertEquals(2, hyperlink3.getFirstRow());
assertEquals(4, hyperlink3.getLastRow());
}
}
@Test @Test
void testCreate() throws Exception { void testCreate() throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook(); XSSFWorkbook workbook = new XSSFWorkbook();
@ -331,7 +352,7 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
} }
@Test @Test
void test() throws IOException { void testCellStyle() throws IOException {
XSSFWorkbook wb = new XSSFWorkbook(); XSSFWorkbook wb = new XSSFWorkbook();
CreationHelper createHelper = wb.getCreationHelper(); CreationHelper createHelper = wb.getCreationHelper();
@ -372,4 +393,47 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
wb.close(); wb.close();
wbBack.close(); wbBack.close();
} }
@Test
void testChangeReference() throws IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFHyperlink hyperlink = new XSSFHyperlink(HyperlinkType.URL);
hyperlink.setCellReference("B2");
assertEquals(1, hyperlink.getFirstRow());
assertEquals(1, hyperlink.getLastRow());
assertEquals(1, hyperlink.getFirstColumn());
assertEquals(1, hyperlink.getLastColumn());
hyperlink.setFirstRow(0);
assertEquals("B1:B2", hyperlink.getCellRef());
assertEquals(0, hyperlink.getFirstRow());
assertEquals(1, hyperlink.getLastRow());
assertEquals(1, hyperlink.getFirstColumn());
assertEquals(1, hyperlink.getLastColumn());
hyperlink.setLastRow(2);
assertEquals("B1:B3", hyperlink.getCellRef());
assertEquals(0, hyperlink.getFirstRow());
assertEquals(2, hyperlink.getLastRow());
assertEquals(1, hyperlink.getFirstColumn());
assertEquals(1, hyperlink.getLastColumn());
hyperlink.setFirstColumn(0);
assertEquals("A1:B3", hyperlink.getCellRef());
assertEquals(0, hyperlink.getFirstRow());
assertEquals(2, hyperlink.getLastRow());
assertEquals(0, hyperlink.getFirstColumn());
assertEquals(1, hyperlink.getLastColumn());
hyperlink.setLastColumn(2);
assertEquals("A1:C3", hyperlink.getCellRef());
assertEquals(0, hyperlink.getFirstRow());
assertEquals(2, hyperlink.getLastRow());
assertEquals(0, hyperlink.getFirstColumn());
assertEquals(2, hyperlink.getLastColumn());
hyperlink.setFirstColumn(2);
hyperlink.setFirstRow(2);
assertEquals("C3", hyperlink.getCellRef());
assertEquals(2, hyperlink.getFirstRow());
assertEquals(2, hyperlink.getLastRow());
assertEquals(2, hyperlink.getFirstColumn());
assertEquals(2, hyperlink.getLastColumn());
}
}
} }

Binary file not shown.