mirror of https://github.com/apache/poi.git
[github-254] Implement XSSFWorkbook linkExternalWorkbook. Thanks to @aspojo. This closes #254
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1893728 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cbaf6def42
commit
bd1ea63abe
|
@ -44,7 +44,8 @@ dependencies {
|
||||||
testImplementation 'org.apache.ant:ant:1.10.11'
|
testImplementation 'org.apache.ant:ant:1.10.11'
|
||||||
testImplementation 'org.apache.commons:commons-collections4:4.4'
|
testImplementation 'org.apache.commons:commons-collections4:4.4'
|
||||||
testImplementation 'com.google.guava:guava:31.0.1-jre'
|
testImplementation 'com.google.guava:guava:31.0.1-jre'
|
||||||
testRuntimeOnly 'org.slf4j:slf4j-api:1.7.32'
|
testRuntimeOnly "org.apache.logging.log4j:log4j-core:${log4jVersion}"
|
||||||
|
testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}"
|
||||||
|
|
||||||
misc(project(':poi-ooxml')) {
|
misc(project(':poi-ooxml')) {
|
||||||
capabilities {
|
capabilities {
|
||||||
|
|
|
@ -18,14 +18,20 @@ package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
import org.apache.poi.common.usermodel.HyperlinkType;
|
import org.apache.poi.common.usermodel.HyperlinkType;
|
||||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||||
|
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||||
|
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.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.CTColor;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class XSSFCreationHelper implements CreationHelper {
|
public class XSSFCreationHelper implements CreationHelper {
|
||||||
private final XSSFWorkbook workbook;
|
private final XSSFWorkbook workbook;
|
||||||
|
private final Map<String, Workbook> referencedWorkbooks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should only be called by {@link XSSFWorkbook#getCreationHelper()}
|
* Should only be called by {@link XSSFWorkbook#getCreationHelper()}
|
||||||
|
@ -35,6 +41,7 @@ public class XSSFCreationHelper implements CreationHelper {
|
||||||
@Internal
|
@Internal
|
||||||
public XSSFCreationHelper(XSSFWorkbook wb) {
|
public XSSFCreationHelper(XSSFWorkbook wb) {
|
||||||
workbook = wb;
|
workbook = wb;
|
||||||
|
referencedWorkbooks = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,7 +81,12 @@ public class XSSFCreationHelper implements CreationHelper {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public XSSFFormulaEvaluator createFormulaEvaluator() {
|
public XSSFFormulaEvaluator createFormulaEvaluator() {
|
||||||
return new XSSFFormulaEvaluator(workbook);
|
XSSFFormulaEvaluator evaluator = new XSSFFormulaEvaluator(workbook);
|
||||||
|
Map<String, FormulaEvaluator> evaluatorMap = new HashMap<>();
|
||||||
|
evaluatorMap.put("", evaluator);
|
||||||
|
this.referencedWorkbooks.forEach((name,otherWorkbook)->evaluatorMap.put(name,otherWorkbook.getCreationHelper().createFormulaEvaluator()));
|
||||||
|
evaluator.setupReferencedWorkbooks(evaluatorMap);
|
||||||
|
return evaluator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,4 +116,12 @@ public class XSSFCreationHelper implements CreationHelper {
|
||||||
public AreaReference createAreaReference(CellReference topLeft, CellReference bottomRight) {
|
public AreaReference createAreaReference(CellReference topLeft, CellReference bottomRight) {
|
||||||
return new AreaReference(topLeft, bottomRight, workbook.getSpreadsheetVersion());
|
return new AreaReference(topLeft, bottomRight, workbook.getSpreadsheetVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Map<String, Workbook> getReferencedWorkbooks() {
|
||||||
|
return referencedWorkbooks;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addExternalWorkbook(String name, Workbook workbook) {
|
||||||
|
this.referencedWorkbooks.put(name,workbook);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,6 +468,8 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
|
||||||
namedRangesByName = new ArrayListValuedHashMap<>();
|
namedRangesByName = new ArrayListValuedHashMap<>();
|
||||||
sheets = new ArrayList<>();
|
sheets = new ArrayList<>();
|
||||||
pivotTables = new ArrayList<>();
|
pivotTables = new ArrayList<>();
|
||||||
|
|
||||||
|
externalLinks = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBookViewsIfMissing() {
|
private void setBookViewsIfMissing() {
|
||||||
|
@ -1971,18 +1973,53 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
|
||||||
* referencing the specified external workbook to be added to this one. Allows
|
* referencing the specified external workbook to be added to this one. Allows
|
||||||
* formulas such as "[MyOtherWorkbook.xlsx]Sheet3!$A$5" to be added to the
|
* formulas such as "[MyOtherWorkbook.xlsx]Sheet3!$A$5" to be added to the
|
||||||
* file, for workbooks not already linked / referenced.
|
* file, for workbooks not already linked / referenced.
|
||||||
*
|
* <p>
|
||||||
* Note: this is not implemented and thus currently throws an Exception stating this.
|
* This support is still regarded as in beta and may change
|
||||||
|
* <p>
|
||||||
|
* see https://bz.apache.org/bugzilla/show_bug.cgi?id=57184
|
||||||
*
|
*
|
||||||
* @param name The name the workbook will be referenced as in formulas
|
* @param name The name the workbook will be referenced as in formulas
|
||||||
* @param workbook The open workbook to fetch the link required information from
|
* @param workbook The open workbook to fetch the link required information from
|
||||||
*
|
* @return index position for external workbook
|
||||||
* @throws RuntimeException stating that this method is not implemented yet.
|
* @since POI 5.1.0
|
||||||
*/
|
*/
|
||||||
|
@Beta
|
||||||
@Override
|
@Override
|
||||||
@NotImplemented
|
|
||||||
public int linkExternalWorkbook(String name, Workbook workbook) {
|
public int linkExternalWorkbook(String name, Workbook workbook) {
|
||||||
throw new RuntimeException("Not Implemented - see bug #57184");
|
int externalLinkIdx=-1;
|
||||||
|
if (!getCreationHelper().getReferencedWorkbooks().containsKey(name)){
|
||||||
|
externalLinkIdx = this.getNextPartNumber(XSSFRelation.EXTERNAL_LINKS,
|
||||||
|
this.getPackagePart().getPackage().getPartsByContentType(XSSFRelation.EXTERNAL_LINKS.getContentType()).size());
|
||||||
|
POIXMLDocumentPart.RelationPart rp = this.createRelationship(XSSFRelation.EXTERNAL_LINKS, XSSFFactory.getInstance(), externalLinkIdx, false);
|
||||||
|
ExternalLinksTable linksTable = rp.getDocumentPart();
|
||||||
|
linksTable.setLinkedFileName(name);
|
||||||
|
this.getExternalLinksTable().add(linksTable);
|
||||||
|
|
||||||
|
CTExternalReference ctExternalReference = this.getCTWorkbook().addNewExternalReferences().addNewExternalReference();
|
||||||
|
ctExternalReference.setId(rp.getRelationship().getId());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
List<RelationPart> relationParts = getRelationParts();
|
||||||
|
for (RelationPart relationPart : relationParts) {
|
||||||
|
if (relationPart.getDocumentPart() instanceof ExternalLinksTable) {
|
||||||
|
ExternalLinksTable linksTable = relationPart.getDocumentPart();
|
||||||
|
String linkedFileName = linksTable.getLinkedFileName();
|
||||||
|
if(linkedFileName.equals(name)){
|
||||||
|
String s = relationPart.getRelationship().getTargetURI().toString();
|
||||||
|
String s2 = XSSFRelation.EXTERNAL_LINKS.getDefaultFileName();
|
||||||
|
String numStr = s.substring(s2.indexOf('#'), s2.indexOf('.'));
|
||||||
|
externalLinkIdx = Integer.parseInt(numStr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XSSFCreationHelper creationHelper = getCreationHelper();
|
||||||
|
creationHelper.addExternalWorkbook(name,workbook);
|
||||||
|
|
||||||
|
return externalLinkIdx;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,9 +19,7 @@ package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
import static org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM;
|
import static org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM;
|
||||||
import static org.apache.poi.hssf.HSSFTestDataSamples.openSampleFileStream;
|
import static org.apache.poi.hssf.HSSFTestDataSamples.openSampleFileStream;
|
||||||
import static org.apache.poi.xssf.XSSFTestDataSamples.openSampleWorkbook;
|
import static org.apache.poi.xssf.XSSFTestDataSamples.*;
|
||||||
import static org.apache.poi.xssf.XSSFTestDataSamples.writeOut;
|
|
||||||
import static org.apache.poi.xssf.XSSFTestDataSamples.writeOutAndReadBack;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
@ -36,6 +34,7 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
|
@ -66,6 +65,7 @@ import org.apache.poi.util.TempFile;
|
||||||
import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
|
import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
|
||||||
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
|
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
|
||||||
import org.apache.poi.xssf.XSSFITestDataProvider;
|
import org.apache.poi.xssf.XSSFITestDataProvider;
|
||||||
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
import org.apache.poi.xssf.model.StylesTable;
|
import org.apache.poi.xssf.model.StylesTable;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCalcPr;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCalcPr;
|
||||||
|
@ -1215,4 +1215,39 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
|
||||||
private static String ref(Cell cell) {
|
private static String ref(Cell cell) {
|
||||||
return new CellReference(cell).formatAsString();
|
return new CellReference(cell).formatAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testLinkExternalWorkbook() throws Exception {
|
||||||
|
String nameA = "link-external-workbook-a.xlsx";
|
||||||
|
|
||||||
|
try (
|
||||||
|
XSSFWorkbook a = new XSSFWorkbook();
|
||||||
|
XSSFWorkbook b = new XSSFWorkbook()
|
||||||
|
) {
|
||||||
|
XSSFRow row1 = a.createSheet().createRow(0);
|
||||||
|
row1.createCell(0).setCellValue(10);
|
||||||
|
row1.createCell(1).setCellValue(20);
|
||||||
|
|
||||||
|
XSSFRow row2 = b.createSheet().createRow(0);
|
||||||
|
XSSFCell cell = row2.createCell(0);
|
||||||
|
|
||||||
|
b.linkExternalWorkbook(nameA, a);
|
||||||
|
String formula = String.format("SUM('[%s]Sheet0'!A1:B1)", nameA);
|
||||||
|
cell.setCellFormula(formula);
|
||||||
|
XSSFFormulaEvaluator evaluator = b.getCreationHelper().createFormulaEvaluator();
|
||||||
|
evaluator.evaluateFormulaCell(cell);
|
||||||
|
double cellValue = cell.getNumericCellValue();
|
||||||
|
assertEquals(cellValue,30.0);
|
||||||
|
/*
|
||||||
|
try (FileOutputStream out = new FileOutputStream(getSampleFile(nameA))) {
|
||||||
|
a.write(out);
|
||||||
|
}
|
||||||
|
String nameB = "link-external-workbook-b.xlsx";
|
||||||
|
try (FileOutputStream out = new FileOutputStream(getSampleFile(nameB))) {
|
||||||
|
b.write(out);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue