support removing hyperlink from one cell when hyperlink is shared by many cells

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1892246 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
PJ Fanning 2021-08-11 21:13:45 +00:00
parent bf6184fd80
commit 4bac6db36b
2 changed files with 96 additions and 11 deletions

View File

@ -3387,15 +3387,56 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
*/
@Internal
public void removeHyperlink(int row, int column) {
// CTHyperlinks is regenerated from scratch when writing out the spreadsheet
// so don't worry about maintaining hyperlinks and CTHyperlinks in parallel.
// only maintain hyperlinks
String ref = new CellReference(row, column).formatAsString();
for (Iterator<XSSFHyperlink> it = hyperlinks.iterator(); it.hasNext();) {
XSSFHyperlink hyperlink = it.next();
if (hyperlink.getCellRef().equals(ref)) {
it.remove();
return;
XSSFHyperlink hyperlink = getHyperlink(row, column);
if (hyperlink != null) {
if (hyperlink.getFirstRow() == row && hyperlink.getLastRow() == row
&& hyperlink.getFirstColumn() == column && hyperlink.getLastColumn() == column) {
removeHyperlink(hyperlink);
} else {
//we have a cellRef that spans multiple cells - we just want to remove the hyperlink from one cell
//we delete this hyperlink but add new hyperlinks to cover the other cells that were served
//by the old hyperlink
boolean leftCreated = false;
boolean rightCreated = false;
if (hyperlink.getFirstColumn() < column) {
XSSFHyperlink newLink = new XSSFHyperlink(hyperlink);
newLink.setFirstColumn(hyperlink.getFirstColumn());
newLink.setLastColumn(column - 1);
newLink.setFirstRow(hyperlink.getFirstRow());
newLink.setLastRow(hyperlink.getLastRow());
addHyperlink(newLink);
leftCreated = true;
}
if (hyperlink.getLastColumn() > column) {
XSSFHyperlink newLink = new XSSFHyperlink(hyperlink);
newLink.setFirstColumn(column + 1);
newLink.setLastColumn(hyperlink.getLastColumn());
newLink.setFirstRow(hyperlink.getFirstRow());
newLink.setLastRow(hyperlink.getLastRow());
addHyperlink(newLink);
rightCreated = true;
}
if (hyperlink.getFirstRow() < row) {
XSSFHyperlink newLink = new XSSFHyperlink(hyperlink);
int firstColumn = leftCreated ? row : hyperlink.getFirstColumn();
int lastColumn = rightCreated ? row : hyperlink.getLastColumn();
newLink.setFirstColumn(firstColumn);
newLink.setLastColumn(lastColumn);
newLink.setFirstRow(hyperlink.getFirstRow());
newLink.setLastRow(row - 1);
addHyperlink(newLink);
}
if (hyperlink.getLastRow() > row) {
XSSFHyperlink newLink = new XSSFHyperlink(hyperlink);
int firstColumn = leftCreated ? row : hyperlink.getFirstColumn();
int lastColumn = rightCreated ? row : hyperlink.getLastColumn();
newLink.setFirstColumn(firstColumn);
newLink.setLastColumn(lastColumn);
newLink.setFirstRow(row + 1);
newLink.setLastRow(hyperlink.getLastRow());
addHyperlink(newLink);
}
removeHyperlink(hyperlink);
}
}
}

View File

@ -22,7 +22,9 @@ import org.apache.poi.hssf.usermodel.HSSFHyperlink;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.ss.SpreadsheetVersion;
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.CellReference;
import org.apache.poi.xssf.XSSFITestDataProvider;
@ -395,7 +397,7 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
}
@Test
void testChangeReference() throws IOException {
void testChangeReference() {
XSSFHyperlink hyperlink = new XSSFHyperlink(HyperlinkType.URL);
hyperlink.setCellReference("B2");
assertEquals(1, hyperlink.getFirstRow());
@ -436,7 +438,7 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
}
@Test
void testChangeRowsAndColumns() throws IOException {
void testChangeRowsAndColumns() {
XSSFHyperlink hyperlink = new XSSFHyperlink(HyperlinkType.URL);
hyperlink.setCellReference("B2");
hyperlink.setLastRow(0);
@ -476,4 +478,46 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
assertEquals(1, hyperlink.getFirstColumn());
assertEquals(2, hyperlink.getLastColumn());
}
@Test
void testRemoveSharedHyperlinkFromOneCell() throws IOException {
testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("C3"));
testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("A1"));
testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("E5"));
testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("E1"));
testRemoveSharedHyperlinkFromOneCell("A1:E5", new CellAddress("A5"));
testRemoveSharedHyperlinkFromOneCell("D3:D5", new CellAddress("D3"));
testRemoveSharedHyperlinkFromOneCell("D3:D5", new CellAddress("D4"));
testRemoveSharedHyperlinkFromOneCell("D3:D5", new CellAddress("D5"));
}
private void testRemoveSharedHyperlinkFromOneCell(String area, CellAddress cellAddress) throws IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet();
XSSFHyperlink hyperlink = new XSSFHyperlink(HyperlinkType.URL);
hyperlink.setAddress("https://poi.apache.org");
hyperlink.setLocation("poi-location");
hyperlink.setLabel("poi-label");
hyperlink.setCellReference(area);
sheet.addHyperlink(hyperlink);
AreaReference areaRef = new AreaReference(hyperlink.getCellRef(), SpreadsheetVersion.EXCEL2007);
for (CellReference cellRef : areaRef.getAllReferencedCells()) {
XSSFHyperlink testHyperlink = sheet.getHyperlink(cellRef.getRow(), cellRef.getCol());
assertEquals(hyperlink, testHyperlink, "cell " + cellRef.formatAsString() + "has hyperlink?");
}
sheet.removeHyperlink(cellAddress.getRow(), cellAddress.getColumn());
assertNull(sheet.getHyperlink(cellAddress), "cell " + cellAddress.formatAsString() + "should no longer has a hyperlink");
for (CellReference cellRef : areaRef.getAllReferencedCells()) {
if (cellRef.formatAsString().equals(cellAddress.formatAsString())) {
//ignore
} else {
XSSFHyperlink testHyperlink = sheet.getHyperlink(cellRef.getRow(), cellRef.getCol());
assertEquals(hyperlink.getAddress(), testHyperlink.getAddress(), "cell " + cellRef.formatAsString() + "has hyperlink with right address?");
assertEquals(hyperlink.getLocation(), testHyperlink.getLocation(), "cell " + cellRef.formatAsString() + "has hyperlink with right location?");
assertEquals(hyperlink.getLabel(), testHyperlink.getLabel(), "cell " + cellRef.formatAsString() + "has hyperlink with right label?");
}
}
}
}
}