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:
Nick Burch 2008-03-21 17:31:14 +00:00
parent 46ac8d5e3e
commit 059ebfaacf
3 changed files with 103 additions and 40 deletions

View File

@ -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" -->

View File

@ -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);

View File

@ -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") +