Tidy up the xssf models stuff, by pushing more of the logic onto XSSFWorkbook
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@637688 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fe2cd2d286
commit
86bac45ee8
@ -39,9 +39,4 @@ public interface SharedStringSource {
|
||||
* @return The 0-based position of the newly added string.
|
||||
*/
|
||||
public int putSharedString(String s);
|
||||
|
||||
/**
|
||||
* Write back out
|
||||
*/
|
||||
public void save() throws IOException;
|
||||
}
|
||||
|
@ -16,14 +16,10 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.usermodel;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface StylesSource {
|
||||
public String getNumberFormatAt(long idx);
|
||||
public long putNumberFormat(String fmt);
|
||||
|
||||
/**
|
||||
* Write back out
|
||||
*/
|
||||
public void save() throws IOException;
|
||||
public Font getFontAt(long idx);
|
||||
public long putFont(Font font);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import java.util.LinkedList;
|
||||
import org.apache.poi.ss.usermodel.SharedStringSource;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.openxml4j.opc.PackagePart;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument;
|
||||
@ -34,32 +33,28 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument;
|
||||
/**
|
||||
* Table of strings shared across all sheets in a workbook.
|
||||
*
|
||||
* FIXME: I don't like having a dependency on PackagePart (from OpenXML4J) in model classes.
|
||||
* I'd rather let Workbook keep track of all part-document relationships and keep all other
|
||||
* classes clean. -- Ugo
|
||||
*
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SharedStringsTable implements SharedStringSource, XSSFModel {
|
||||
|
||||
private final LinkedList<String> strings = new LinkedList<String>();
|
||||
private SstDocument doc;
|
||||
|
||||
private PackagePart part;
|
||||
|
||||
/**
|
||||
* Create a new SharedStringsTable by reading it from a PackagePart.
|
||||
* Create a new SharedStringsTable, by reading it
|
||||
* from the InputStream of a PackagePart.
|
||||
*
|
||||
* @param part The PackagePart to read.
|
||||
* @param is The input stream containing the XML document.
|
||||
* @throws IOException if an error occurs while reading.
|
||||
*/
|
||||
public SharedStringsTable(PackagePart part) throws IOException {
|
||||
this.part = part;
|
||||
InputStream is = part.getInputStream();
|
||||
try {
|
||||
readFrom(is);
|
||||
} finally {
|
||||
if (is != null) is.close();
|
||||
}
|
||||
public SharedStringsTable(InputStream is) throws IOException {
|
||||
readFrom(is);
|
||||
}
|
||||
/**
|
||||
* Create a new, empty SharedStringsTable
|
||||
*/
|
||||
public SharedStringsTable() {
|
||||
doc = SstDocument.Factory.newInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,7 +65,7 @@ public class SharedStringsTable implements SharedStringSource, XSSFModel {
|
||||
*/
|
||||
public void readFrom(InputStream is) throws IOException {
|
||||
try {
|
||||
SstDocument doc = SstDocument.Factory.parse(is);
|
||||
doc = SstDocument.Factory.parse(is);
|
||||
for (CTRst rst : doc.getSst().getSiArray()) {
|
||||
strings.add(rst.getT());
|
||||
}
|
||||
@ -91,20 +86,6 @@ public class SharedStringsTable implements SharedStringSource, XSSFModel {
|
||||
return strings.size() - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save this table to its own PackagePart.
|
||||
*
|
||||
* @throws IOException if an error occurs while writing.
|
||||
*/
|
||||
public void save() throws IOException {
|
||||
OutputStream out = this.part.getOutputStream();
|
||||
try {
|
||||
writeTo(out);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this table out as XML.
|
||||
*
|
||||
|
@ -25,13 +25,14 @@ import java.util.Hashtable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.StylesSource;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.openxml4j.opc.PackagePart;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFonts;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmt;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmts;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;;
|
||||
@ -40,10 +41,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;;
|
||||
/**
|
||||
* Table of styles shared across all sheets in a workbook.
|
||||
*
|
||||
* FIXME: I don't like having a dependency on PackagePart (from OpenXML4J) in model classes.
|
||||
* I'd rather let Workbook keep track of all part-document relationships and keep all other
|
||||
* classes clean. -- Ugo
|
||||
*
|
||||
* @version $Id: SharedStringsTable.java 612495 2008-01-16 16:08:22Z ugo $
|
||||
*/
|
||||
public class StylesTable implements StylesSource, XSSFModel {
|
||||
@ -52,23 +49,28 @@ public class StylesTable implements StylesSource, XSSFModel {
|
||||
private final LinkedList<CTFill> fills = new LinkedList<CTFill>();
|
||||
private final LinkedList<CTBorder> borders = new LinkedList<CTBorder>();
|
||||
|
||||
private PackagePart part;
|
||||
/**
|
||||
* The first style id available for use as a custom style
|
||||
*/
|
||||
public static final long FIRST_CUSTOM_STYLE_ID = 165;
|
||||
|
||||
private StyleSheetDocument doc;
|
||||
|
||||
/**
|
||||
* Create a new StylesTable by reading it from a PackagePart.
|
||||
* Create a new StylesTable, by reading it from
|
||||
* the InputStream of a a PackagePart.
|
||||
*
|
||||
* @param part The PackagePart to read.
|
||||
* @param is The input stream containing the XML document.
|
||||
* @throws IOException if an error occurs while reading.
|
||||
*/
|
||||
public StylesTable(PackagePart part) throws IOException {
|
||||
this.part = part;
|
||||
InputStream is = part.getInputStream();
|
||||
try {
|
||||
readFrom(is);
|
||||
} finally {
|
||||
if (is != null) is.close();
|
||||
}
|
||||
public StylesTable(InputStream is) throws IOException {
|
||||
readFrom(is);
|
||||
}
|
||||
/**
|
||||
* Create a new, empty StylesTable
|
||||
*/
|
||||
public StylesTable() {
|
||||
doc = StyleSheetDocument.Factory.newInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,7 +108,6 @@ public class StylesTable implements StylesSource, XSSFModel {
|
||||
public String getNumberFormatAt(long idx) {
|
||||
return numberFormats.get(idx);
|
||||
}
|
||||
|
||||
public synchronized long putNumberFormat(String fmt) {
|
||||
if (numberFormats.containsValue(fmt)) {
|
||||
// Find the key, and return that
|
||||
@ -120,7 +121,7 @@ public class StylesTable implements StylesSource, XSSFModel {
|
||||
}
|
||||
|
||||
// Find a spare key, and add that
|
||||
long newKey = 1;
|
||||
long newKey = FIRST_CUSTOM_STYLE_ID;
|
||||
while(numberFormats.containsKey(newKey)) {
|
||||
newKey++;
|
||||
}
|
||||
@ -128,6 +129,15 @@ public class StylesTable implements StylesSource, XSSFModel {
|
||||
return newKey;
|
||||
}
|
||||
|
||||
public Font getFontAt(long idx) {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
public synchronized long putFont(Font font) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* For unit testing only
|
||||
*/
|
||||
@ -154,20 +164,6 @@ public class StylesTable implements StylesSource, XSSFModel {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save this table to its own PackagePart.
|
||||
*
|
||||
* @throws IOException if an error occurs while writing.
|
||||
*/
|
||||
public void save() throws IOException {
|
||||
OutputStream out = this.part.getOutputStream();
|
||||
try {
|
||||
writeTo(out);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this table out as XML.
|
||||
*
|
||||
@ -193,7 +189,12 @@ public class StylesTable implements StylesSource, XSSFModel {
|
||||
doc.getStyleSheet().setNumFmts(formats);
|
||||
|
||||
// Fonts
|
||||
// TODO
|
||||
CTFonts fnts = CTFonts.Factory.newInstance();
|
||||
fnts.setCount(fonts.size());
|
||||
fnts.setFontArray(
|
||||
fonts.toArray(new CTFont[fonts.size()])
|
||||
);
|
||||
doc.getStyleSheet().setFonts(fnts);
|
||||
|
||||
// Fills
|
||||
// TODO
|
||||
|
@ -18,7 +18,9 @@
|
||||
package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -65,22 +67,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
|
||||
|
||||
|
||||
public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||
public static class XSSFRelation {
|
||||
private String TYPE;
|
||||
private String REL;
|
||||
private String DEFAULT_NAME;
|
||||
private Class<? extends XSSFModel> CLASS;
|
||||
private XSSFRelation(String TYPE, String REL, String DEFAULT_NAME, Class<? extends XSSFModel> CLASS) {
|
||||
this.TYPE = TYPE;
|
||||
this.REL = REL;
|
||||
this.DEFAULT_NAME = DEFAULT_NAME;
|
||||
this.CLASS = CLASS;
|
||||
}
|
||||
public String getContentType() { return TYPE; }
|
||||
public String getRelation() { return REL; }
|
||||
public String getDefaultFileName() { return DEFAULT_NAME; }
|
||||
}
|
||||
|
||||
public static final XSSFRelation WORKSHEET = new XSSFRelation(
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
|
||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
|
||||
@ -112,6 +98,70 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||
null
|
||||
);
|
||||
|
||||
public static class XSSFRelation {
|
||||
private String TYPE;
|
||||
private String REL;
|
||||
private String DEFAULT_NAME;
|
||||
private Class<? extends XSSFModel> CLASS;
|
||||
private XSSFRelation(String TYPE, String REL, String DEFAULT_NAME, Class<? extends XSSFModel> CLASS) {
|
||||
this.TYPE = TYPE;
|
||||
this.REL = REL;
|
||||
this.DEFAULT_NAME = DEFAULT_NAME;
|
||||
this.CLASS = CLASS;
|
||||
}
|
||||
public String getContentType() { return TYPE; }
|
||||
public String getRelation() { return REL; }
|
||||
public String getDefaultFileName() { return DEFAULT_NAME; }
|
||||
|
||||
/**
|
||||
* Load, off the specified core part
|
||||
*/
|
||||
private XSSFModel load(PackagePart corePart) throws Exception {
|
||||
Constructor<? extends XSSFModel> c = CLASS.getConstructor(InputStream.class);
|
||||
XSSFModel model = null;
|
||||
|
||||
PackageRelationshipCollection prc =
|
||||
corePart.getRelationshipsByType(REL);
|
||||
Iterator<PackageRelationship> it = prc.iterator();
|
||||
if(it.hasNext()) {
|
||||
PackageRelationship rel = it.next();
|
||||
PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
|
||||
PackagePart part = corePart.getPackage().getPart(relName);
|
||||
InputStream is = part.getInputStream();
|
||||
try {
|
||||
model = c.newInstance(is);
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
} else {
|
||||
log.log(POILogger.WARN, "No part " + DEFAULT_NAME + " found");
|
||||
}
|
||||
return model;
|
||||
}
|
||||
/**
|
||||
* Save, with the default name
|
||||
*/
|
||||
private void save(XSSFModel model, PackagePart corePart) throws IOException {
|
||||
save(model, corePart, DEFAULT_NAME);
|
||||
}
|
||||
/**
|
||||
* Save, with the specified name
|
||||
*/
|
||||
private void save(XSSFModel model, PackagePart corePart, String name) throws IOException {
|
||||
PackagePartName ppName = null;
|
||||
try {
|
||||
ppName = PackagingURIHelper.createPartName(name);
|
||||
} catch(InvalidFormatException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
corePart.addRelationship(ppName, TargetMode.INTERNAL, REL);
|
||||
PackagePart part = corePart.getPackage().createPart(ppName, TYPE);
|
||||
OutputStream out = part.getOutputStream();
|
||||
model.writeTo(out);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
private CTWorkbook workbook;
|
||||
|
||||
private List<XSSFSheet> sheets = new LinkedList<XSSFSheet>();
|
||||
@ -138,34 +188,22 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||
WorkbookDocument doc = WorkbookDocument.Factory.parse(getCorePart().getInputStream());
|
||||
this.workbook = doc.getWorkbook();
|
||||
|
||||
PackageRelationshipCollection prc;
|
||||
Iterator<PackageRelationship> it;
|
||||
|
||||
// Load shared strings
|
||||
prc = getCorePart().getRelationshipsByType(SHARED_STRINGS.getRelation());
|
||||
it = prc.iterator();
|
||||
if (it.hasNext()) {
|
||||
PackageRelationship rel = it.next();
|
||||
PackagePart part = getTargetPart(rel);
|
||||
this.sharedStringSource = new SharedStringsTable(part);
|
||||
} else {
|
||||
log.log(POILogger.WARN, "No shared strings part found");
|
||||
}
|
||||
// Load styles source
|
||||
prc = getCorePart().getRelationshipsByType(STYLES.getRelation());
|
||||
it = prc.iterator();
|
||||
if (it.hasNext()) {
|
||||
PackageRelationship rel = it.next();
|
||||
PackagePart part = getTargetPart(rel);
|
||||
this.stylesSource = new StylesTable(part);
|
||||
} else {
|
||||
log.log(POILogger.WARN, "No styles part found");
|
||||
try {
|
||||
// Load shared strings
|
||||
this.sharedStringSource = (SharedStringSource)
|
||||
SHARED_STRINGS.load(getCorePart());
|
||||
// Load styles source
|
||||
this.stylesSource = (StylesSource)
|
||||
STYLES.load(getCorePart());
|
||||
} catch(Exception e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
|
||||
// Load individual sheets
|
||||
for (CTSheet ctSheet : this.workbook.getSheets().getSheetArray()) {
|
||||
PackagePart part = getPackagePart(ctSheet);
|
||||
if (part == null) {
|
||||
log.log(POILogger.WARN, "Sheet with name " + ctSheet.getName() + " was defined, but didn't exist, skipping");
|
||||
continue;
|
||||
}
|
||||
WorksheetDocument worksheetDoc = WorksheetDocument.Factory.parse(part.getInputStream());
|
||||
@ -572,21 +610,11 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||
// Write shared strings and styles
|
||||
if(sharedStringSource != null) {
|
||||
SharedStringsTable sst = (SharedStringsTable)sharedStringSource;
|
||||
PackagePartName sstName = PackagingURIHelper.createPartName(SHARED_STRINGS.getDefaultFileName());
|
||||
corePart.addRelationship(sstName, TargetMode.INTERNAL, SHARED_STRINGS.getRelation());
|
||||
PackagePart sstPart = pkg.createPart(sstName, SHARED_STRINGS.getContentType());
|
||||
out = sstPart.getOutputStream();
|
||||
sst.writeTo(out);
|
||||
out.close();
|
||||
SHARED_STRINGS.save(sst, corePart);
|
||||
}
|
||||
if(stylesSource != null) {
|
||||
StylesTable st = (StylesTable)stylesSource;
|
||||
PackagePartName stName = PackagingURIHelper.createPartName(STYLES.getDefaultFileName());
|
||||
corePart.addRelationship(stName, TargetMode.INTERNAL, STYLES.getRelation());
|
||||
PackagePart stPart = pkg.createPart(stName, STYLES.getContentType());
|
||||
out = stPart.getOutputStream();
|
||||
st.writeTo(out);
|
||||
out.close();
|
||||
STYLES.save(st, corePart);
|
||||
}
|
||||
|
||||
// All done
|
||||
|
@ -31,8 +31,17 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook;
|
||||
|
||||
|
||||
public class TestXSSFWorkbook extends TestCase {
|
||||
|
||||
public void testGetSheetIndex() {
|
||||
public TestXSSFWorkbook(String name) {
|
||||
super(name);
|
||||
|
||||
// Use system out logger
|
||||
System.setProperty(
|
||||
"org.apache.poi.util.POILogger",
|
||||
"org.apache.poi.util.SystemOutLogger"
|
||||
);
|
||||
}
|
||||
|
||||
public void testGetSheetIndex() {
|
||||
XSSFWorkbook workbook = new XSSFWorkbook();
|
||||
Sheet sheet1 = workbook.createSheet("sheet1");
|
||||
Sheet sheet2 = workbook.createSheet("sheet2");
|
||||
@ -127,7 +136,7 @@ public class TestXSSFWorkbook extends TestCase {
|
||||
Sheet sheet2 = workbook.createSheet("sheet2");
|
||||
Sheet sheet3 = workbook.createSheet("sheet3");
|
||||
File file = File.createTempFile("poi-", ".xlsx");
|
||||
System.out.println("Saving to " + file.getAbsolutePath());
|
||||
System.out.println("Saving newly created file to " + file.getAbsolutePath());
|
||||
OutputStream out = new FileOutputStream(file);
|
||||
workbook.write(out);
|
||||
out.close();
|
||||
@ -194,5 +203,17 @@ public class TestXSSFWorkbook extends TestCase {
|
||||
assertEquals(2, st._getFillsSize());
|
||||
// Has 1 border
|
||||
assertEquals(1, st._getBordersSize());
|
||||
|
||||
// Add two more styles
|
||||
assertEquals(StylesTable.FIRST_CUSTOM_STYLE_ID + 8,
|
||||
st.putNumberFormat("testFORMAT"));
|
||||
assertEquals(StylesTable.FIRST_CUSTOM_STYLE_ID + 8,
|
||||
st.putNumberFormat("testFORMAT"));
|
||||
assertEquals(StylesTable.FIRST_CUSTOM_STYLE_ID + 9,
|
||||
st.putNumberFormat("testFORMAT2"));
|
||||
assertEquals(10, st._getNumberFormatSize());
|
||||
|
||||
// Save, load back in again, and check
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user