From: PJ Fanning Date: Mon, 9 Aug 2021 21:57:40 +0000 (+0000) Subject: add support for reading hyperlinks that have cell refs that are area references ... X-Git-Tag: REL_5_1_0~53 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7bcf6d5a6d1ae77aef4e3f9ff6d6b4d23fb6a8b5;p=poi.git 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 --- diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java index 6c5f792065..8913859a2f 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java @@ -22,7 +22,9 @@ import java.net.URISyntaxException; import org.apache.poi.common.usermodel.HyperlinkType; import org.apache.poi.openxml4j.opc.PackagePart; 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.util.AreaReference; import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.Internal; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink; @@ -264,20 +266,32 @@ public class XSSFHyperlink implements Hyperlink { public void setCellReference(String ref) { _ctHyperlink.setRef(ref); } + @Internal public void setCellReference(CellReference ref) { 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(); if (ref == null) { ref = "A1"; } + if (ref.contains(":")) { + AreaReference area = new AreaReference(ref, SpreadsheetVersion.EXCEL2007); + return lastCell ? area.getLastCell() : area.getFirstCell(); + } return new CellReference(ref); } - /** * Return the column of the first cell that contains the hyperlink * @@ -285,7 +299,7 @@ public class XSSFHyperlink implements Hyperlink { */ @Override public int getFirstColumn() { - return buildCellReference().getCol(); + return buildFirstCellReference().getCol(); } @@ -296,7 +310,7 @@ public class XSSFHyperlink implements Hyperlink { */ @Override public int getLastColumn() { - return buildCellReference().getCol(); + return buildLastCellReference().getCol(); } /** @@ -306,7 +320,7 @@ public class XSSFHyperlink implements Hyperlink { */ @Override public int getFirstRow() { - return buildCellReference().getRow(); + return buildFirstCellReference().getRow(); } @@ -317,7 +331,7 @@ public class XSSFHyperlink implements Hyperlink { */ @Override public int getLastRow() { - return buildCellReference().getRow(); + return buildLastCellReference().getRow(); } /** @@ -327,18 +341,19 @@ public class XSSFHyperlink implements Hyperlink { */ @Override 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. - * For XSSF, a Hyperlink may only reference one cell * * @param col the 0-based column of the last cell that contains the hyperlink */ @Override 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 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. - * For XSSF, a Hyperlink may only reference one cell * * @param row the 0-based row of the last cell that contains the hyperlink */ @Override 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()); + } } /** diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 27ad23611e..bf3e7396d3 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -55,23 +55,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.formula.SheetNameFormatter; -import org.apache.poi.ss.usermodel.Cell; -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.usermodel.*; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellAddress; import org.apache.poi.ss.util.CellRangeAddress; @@ -846,9 +830,9 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { */ @Override public XSSFHyperlink getHyperlink(CellAddress addr) { - String ref = addr.formatAsString(); - for(XSSFHyperlink hyperlink : hyperlinks) { - if(hyperlink.getCellRef().equals(ref)) { + for (XSSFHyperlink hyperlink : getHyperlinkList()) { + if (addr.getRow() >= hyperlink.getFirstRow() && addr.getRow() <= hyperlink.getLastRow() + && addr.getColumn() >= hyperlink.getFirstColumn() && addr.getColumn() <= hyperlink.getLastColumn()) { return hyperlink; } } diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java index 203fbba80c..e95a07d20d 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java @@ -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 void testCreate() throws Exception { XSSFWorkbook workbook = new XSSFWorkbook(); @@ -331,7 +352,7 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink { } @Test - void test() throws IOException { + void testCellStyle() throws IOException { XSSFWorkbook wb = new XSSFWorkbook(); CreationHelper createHelper = wb.getCreationHelper(); @@ -372,4 +393,47 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink { wb.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()); + } + } } diff --git a/test-data/spreadsheet/sharedhyperlink.xlsx b/test-data/spreadsheet/sharedhyperlink.xlsx new file mode 100644 index 0000000000..d314997707 Binary files /dev/null and b/test-data/spreadsheet/sharedhyperlink.xlsx differ