mirror of https://github.com/apache/poi.git
New openxml4j. Also, re-order some of the xssfworkbook writing out steps, so we can update references. Finally, some more tests
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@639723 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
46ac8d5e3e
commit
059ebfaacf
|
@ -147,8 +147,8 @@ under the License.
|
||||||
<property name="ooxml.jar5.dir" location="${ooxml.lib}/jsr173_1.0_api.jar"/>
|
<property name="ooxml.jar5.dir" location="${ooxml.lib}/jsr173_1.0_api.jar"/>
|
||||||
<property name="ooxml.jar5.url" value="${repository}/xmlbeans/jars/jsr173_1.0_api.jar"/>
|
<property name="ooxml.jar5.url" value="${repository}/xmlbeans/jars/jsr173_1.0_api.jar"/>
|
||||||
<!-- No official release of openxml4j yet -->
|
<!-- No official release of openxml4j yet -->
|
||||||
<property name="ooxml.jar6.dir" location="${ooxml.lib}/openxml4j-bin-alpha-080311.jar"/>
|
<property name="ooxml.jar6.dir" location="${ooxml.lib}/openxml4j-bin-alpha-080321.jar"/>
|
||||||
<property name="ooxml.jar6.url" value="http://people.apache.org/~nick/openxml4j-bin-alpha-080311.jar"/>
|
<property name="ooxml.jar6.url" value="http://people.apache.org/~nick/openxml4j-bin-alpha-080321.jar"/>
|
||||||
|
|
||||||
<!-- See http://www.ecma-international.org/publications/standards/Ecma-376.htm -->
|
<!-- See http://www.ecma-international.org/publications/standards/Ecma-376.htm -->
|
||||||
<!-- "Copy these file(s), free of charge" -->
|
<!-- "Copy these file(s), free of charge" -->
|
||||||
|
|
|
@ -67,6 +67,12 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
|
||||||
|
|
||||||
|
|
||||||
public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||||
|
public static final XSSFRelation WORKBOOK = new XSSFRelation(
|
||||||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/workbook",
|
||||||
|
"/xl/workbook.xml",
|
||||||
|
null
|
||||||
|
);
|
||||||
public static final XSSFRelation WORKSHEET = new XSSFRelation(
|
public static final XSSFRelation WORKSHEET = new XSSFRelation(
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
|
||||||
|
@ -140,25 +146,30 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Save, with the default name
|
* Save, with the default name
|
||||||
|
* @return The internal reference ID it was saved at, normally then used as an r:id
|
||||||
*/
|
*/
|
||||||
private void save(XSSFModel model, PackagePart corePart) throws IOException {
|
private String save(XSSFModel model, PackagePart corePart) throws IOException {
|
||||||
save(model, corePart, DEFAULT_NAME);
|
return save(model, corePart, DEFAULT_NAME);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Save, with the specified name
|
* Save, with the specified name
|
||||||
|
* @return The internal reference ID it was saved at, normally then used as an r:id
|
||||||
*/
|
*/
|
||||||
private void save(XSSFModel model, PackagePart corePart, String name) throws IOException {
|
private String save(XSSFModel model, PackagePart corePart, String name) throws IOException {
|
||||||
PackagePartName ppName = null;
|
PackagePartName ppName = null;
|
||||||
try {
|
try {
|
||||||
ppName = PackagingURIHelper.createPartName(name);
|
ppName = PackagingURIHelper.createPartName(name);
|
||||||
} catch(InvalidFormatException e) {
|
} catch(InvalidFormatException e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
corePart.addRelationship(ppName, TargetMode.INTERNAL, REL);
|
PackageRelationship rel =
|
||||||
|
corePart.addRelationship(ppName, TargetMode.INTERNAL, REL);
|
||||||
PackagePart part = corePart.getPackage().createPart(ppName, TYPE);
|
PackagePart part = corePart.getPackage().createPart(ppName, TYPE);
|
||||||
OutputStream out = part.getOutputStream();
|
OutputStream out = part.getOutputStream();
|
||||||
model.writeTo(out);
|
model.writeTo(out);
|
||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
|
return rel.getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +214,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||||
for (CTSheet ctSheet : this.workbook.getSheets().getSheetArray()) {
|
for (CTSheet ctSheet : this.workbook.getSheets().getSheetArray()) {
|
||||||
PackagePart part = getPackagePart(ctSheet);
|
PackagePart part = getPackagePart(ctSheet);
|
||||||
if (part == null) {
|
if (part == null) {
|
||||||
log.log(POILogger.WARN, "Sheet with name " + ctSheet.getName() + " was defined, but didn't exist, skipping");
|
log.log(POILogger.WARN, "Sheet with name " + ctSheet.getName() + " and r:id " + ctSheet.getId()+ " was defined, but didn't exist in package, skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
WorksheetDocument worksheetDoc = WorksheetDocument.Factory.parse(part.getInputStream());
|
WorksheetDocument worksheetDoc = WorksheetDocument.Factory.parse(part.getInputStream());
|
||||||
|
@ -231,7 +242,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||||
private PackagePart getPackagePart(CTSheet ctSheet) throws InvalidFormatException {
|
private PackagePart getPackagePart(CTSheet ctSheet) throws InvalidFormatException {
|
||||||
PackageRelationship rel = this.getCorePart().getRelationship(ctSheet.getId());
|
PackageRelationship rel = this.getCorePart().getRelationship(ctSheet.getId());
|
||||||
if (rel == null) {
|
if (rel == null) {
|
||||||
log.log(POILogger.WARN, "No relationship found for sheet " + ctSheet.getId());
|
log.log(POILogger.WARN, "No relationship found for sheet " + ctSheet.getId() + " - core part has " + this.getCorePart().getRelationships().size() + " relations defined");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return getTargetPart(rel);
|
return getTargetPart(rel);
|
||||||
|
@ -579,46 +590,55 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||||
// Create main part relationship
|
// Create main part relationship
|
||||||
pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT, "rId1");
|
pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT, "rId1");
|
||||||
// Create main document part
|
// Create main document part
|
||||||
PackagePart corePart = pkg.createPart(corePartName,
|
PackagePart corePart = pkg.createPart(corePartName, WORKBOOK.getContentType());
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
|
OutputStream out;
|
||||||
|
|
||||||
XmlOptions xmlOptions = new XmlOptions();
|
XmlOptions xmlOptions = new XmlOptions();
|
||||||
// Requests use of whitespace for easier reading
|
// Requests use of whitespace for easier reading
|
||||||
xmlOptions.setSavePrettyPrint();
|
xmlOptions.setSavePrettyPrint();
|
||||||
xmlOptions.setSaveOuter();
|
xmlOptions.setSaveOuter();
|
||||||
// XXX This should not be needed, but apparently the setSaveOuter call above does not work in XMLBeans 2.2
|
xmlOptions.setUseDefaultNamespace();
|
||||||
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorkbook.type.getName().getNamespaceURI(), "workbook"));
|
|
||||||
xmlOptions.setUseDefaultNamespace();
|
|
||||||
|
|
||||||
OutputStream out = corePart.getOutputStream();
|
// Write out our sheets, updating the references
|
||||||
workbook.save(out, xmlOptions);
|
// to them in the main workbook as we go
|
||||||
out.close();
|
for (int i=0 ; i < this.getNumberOfSheets(); i++) {
|
||||||
|
int sheetNumber = (i+1);
|
||||||
|
XSSFSheet sheet = (XSSFSheet) this.getSheetAt(i);
|
||||||
|
PackagePartName partName = PackagingURIHelper.createPartName("/xl/worksheets/sheet" + sheetNumber + ".xml");
|
||||||
|
PackageRelationship rel =
|
||||||
|
corePart.addRelationship(partName, TargetMode.INTERNAL, WORKSHEET.getRelation(), "rSheet" + sheetNumber);
|
||||||
|
PackagePart part = pkg.createPart(partName, WORKSHEET.getContentType());
|
||||||
|
|
||||||
for (int i = 0 ; i < this.getNumberOfSheets() ; ++i) {
|
// XXX This should not be needed, but apparently the setSaveOuter call above does not work in XMLBeans 2.2
|
||||||
XSSFSheet sheet = (XSSFSheet) this.getSheetAt(i);
|
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet"));
|
||||||
PackagePartName partName = PackagingURIHelper.createPartName("/xl/worksheets/sheet" + i + ".xml");
|
out = part.getOutputStream();
|
||||||
corePart.addRelationship(partName, TargetMode.INTERNAL, WORKSHEET.getRelation(), "rSheet" + 1);
|
sheet.getWorksheet().save(out, xmlOptions);
|
||||||
PackagePart part = pkg.createPart(partName, WORKSHEET.getContentType());
|
out.close();
|
||||||
|
|
||||||
// XXX This should not be needed, but apparently the setSaveOuter call above does not work in XMLBeans 2.2
|
// Update our internal reference for the package part
|
||||||
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet"));
|
workbook.getSheets().getSheetArray(i).setId(rel.getId());
|
||||||
out = part.getOutputStream();
|
}
|
||||||
sheet.getWorksheet().save(out, xmlOptions);
|
|
||||||
|
|
||||||
out.close();
|
// Write shared strings and styles
|
||||||
}
|
if(sharedStringSource != null) {
|
||||||
|
|
||||||
// Write shared strings and styles
|
|
||||||
if(sharedStringSource != null) {
|
|
||||||
SharedStringsTable sst = (SharedStringsTable)sharedStringSource;
|
SharedStringsTable sst = (SharedStringsTable)sharedStringSource;
|
||||||
SHARED_STRINGS.save(sst, corePart);
|
SHARED_STRINGS.save(sst, corePart);
|
||||||
}
|
}
|
||||||
if(stylesSource != null) {
|
if(stylesSource != null) {
|
||||||
StylesTable st = (StylesTable)stylesSource;
|
StylesTable st = (StylesTable)stylesSource;
|
||||||
STYLES.save(st, corePart);
|
STYLES.save(st, corePart);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All done
|
// Now we can write out the main Workbook, with
|
||||||
pkg.close();
|
// the correct references to the other parts
|
||||||
|
out = corePart.getOutputStream();
|
||||||
|
// XXX This should not be needed, but apparently the setSaveOuter call above does not work in XMLBeans 2.2
|
||||||
|
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorkbook.type.getName().getNamespaceURI(), "workbook"));
|
||||||
|
workbook.save(out, xmlOptions);
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
// All done
|
||||||
|
pkg.close();
|
||||||
} catch (InvalidFormatException e) {
|
} catch (InvalidFormatException e) {
|
||||||
// TODO: replace with more meaningful exception
|
// TODO: replace with more meaningful exception
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|
|
@ -130,7 +130,10 @@ public class TestXSSFWorkbook extends TestCase {
|
||||||
assertEquals(0, workbook.getNumberOfSheets());
|
assertEquals(0, workbook.getNumberOfSheets());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSave() throws Exception {
|
/**
|
||||||
|
* Tests that we can save a new document
|
||||||
|
*/
|
||||||
|
public void testSaveNew() throws Exception {
|
||||||
XSSFWorkbook workbook = new XSSFWorkbook();
|
XSSFWorkbook workbook = new XSSFWorkbook();
|
||||||
Sheet sheet1 = workbook.createSheet("sheet1");
|
Sheet sheet1 = workbook.createSheet("sheet1");
|
||||||
Sheet sheet2 = workbook.createSheet("sheet2");
|
Sheet sheet2 = workbook.createSheet("sheet2");
|
||||||
|
@ -142,6 +145,46 @@ public class TestXSSFWorkbook extends TestCase {
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that we can save, and then re-load a new document
|
||||||
|
*/
|
||||||
|
public void testSaveLoadNew() throws Exception {
|
||||||
|
XSSFWorkbook workbook = new XSSFWorkbook();
|
||||||
|
Sheet sheet1 = workbook.createSheet("sheet1");
|
||||||
|
Sheet sheet2 = workbook.createSheet("sheet2");
|
||||||
|
Sheet sheet3 = workbook.createSheet("sheet3");
|
||||||
|
|
||||||
|
sheet1.createRow(0);
|
||||||
|
sheet1.createRow(1);
|
||||||
|
sheet2.createRow(0);
|
||||||
|
|
||||||
|
assertEquals(0, workbook.getSheetAt(0).getFirstRowNum());
|
||||||
|
assertEquals(1, workbook.getSheetAt(0).getLastRowNum());
|
||||||
|
assertEquals(0, workbook.getSheetAt(1).getFirstRowNum());
|
||||||
|
assertEquals(0, workbook.getSheetAt(1).getLastRowNum());
|
||||||
|
assertEquals(-1, workbook.getSheetAt(2).getFirstRowNum());
|
||||||
|
assertEquals(-1, workbook.getSheetAt(2).getLastRowNum());
|
||||||
|
|
||||||
|
File file = File.createTempFile("poi-", ".xlsx");
|
||||||
|
OutputStream out = new FileOutputStream(file);
|
||||||
|
workbook.write(out);
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
// Load back in again
|
||||||
|
workbook = new XSSFWorkbook(file.toString());
|
||||||
|
assertEquals(3, workbook.getNumberOfSheets());
|
||||||
|
assertNotNull(workbook.getSheetAt(0));
|
||||||
|
assertNotNull(workbook.getSheetAt(1));
|
||||||
|
assertNotNull(workbook.getSheetAt(2));
|
||||||
|
|
||||||
|
assertEquals(0, workbook.getSheetAt(0).getFirstRowNum());
|
||||||
|
assertEquals(1, workbook.getSheetAt(0).getLastRowNum());
|
||||||
|
assertEquals(0, workbook.getSheetAt(1).getFirstRowNum());
|
||||||
|
assertEquals(0, workbook.getSheetAt(1).getLastRowNum());
|
||||||
|
assertEquals(-1, workbook.getSheetAt(2).getFirstRowNum());
|
||||||
|
assertEquals(-1, workbook.getSheetAt(2).getLastRowNum());
|
||||||
|
}
|
||||||
|
|
||||||
public void testExisting() throws Exception {
|
public void testExisting() throws Exception {
|
||||||
File xml = new File(
|
File xml = new File(
|
||||||
System.getProperty("HSSF.testdata.path") +
|
System.getProperty("HSSF.testdata.path") +
|
||||||
|
|
Loading…
Reference in New Issue