import org.openxml4j.exceptions.InvalidFormatException;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackagePartName;
-import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackagingURIHelper;
import org.openxml4j.opc.TargetMode;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTControl;
options.setSavePrettyPrint();
control.save(out, options);
}
+
+ /**
+ * We expect active x binary parts
+ */
+ public String[] getChildrenRelationshipTypes() {
+ return new String[] {
+ XSSFWorkbook.ACTIVEX_BINS.getRelation()
+ };
+ }
/**
- * Finds our XSSFActiveXData children
+ * Generates and adds XSSFActiveXData children
*/
- public void findChildren(PackagePart modelPart) throws IOException, InvalidFormatException {
- for(PackageRelationship rel : modelPart.getRelationshipsByType(XSSFWorkbook.ACTIVEX_BINS.getRelation())) {
- PackagePart binPart = XSSFWorkbook.getTargetPart(modelPart.getPackage(), rel);
- XSSFActiveXData actX = new XSSFActiveXData(binPart, rel.getId());
- activexBins.add(actX);
- }
+ public void generateChild(PackagePart childPart, String childRelId) {
+ XSSFActiveXData actX = new XSSFActiveXData(childPart, childRelId);
+ activexBins.add(actX);
}
+
/**
* Writes back out our XSSFPictureData children
*/
import org.openxml4j.exceptions.InvalidFormatException;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackagePartName;
-import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackagingURIHelper;
import org.openxml4j.opc.TargetMode;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDrawing;
}
/**
- * Finds our XSSFPictureData children
+ * We expect image parts
*/
- public void findChildren(PackagePart modelPart) throws IOException, InvalidFormatException {
- for(PackageRelationship rel : modelPart.getRelationshipsByType(XSSFWorkbook.IMAGES.getRelation())) {
- PackagePart imagePart = XSSFWorkbook.getTargetPart(modelPart.getPackage(), rel);
- XSSFPictureData pd = new XSSFPictureData(imagePart, rel.getId());
- pictures.add(pd);
- }
+ public String[] getChildrenRelationshipTypes() {
+ return new String[] {
+ XSSFWorkbook.IMAGES.getRelation()
+ };
+ }
+
+ /**
+ * Generates and adds XSSFActiveXData children
+ */
+ public void generateChild(PackagePart childPart, String childRelId) {
+ XSSFPictureData pd = new XSSFPictureData(childPart, childRelId);
+ pictures.add(pd);
}
+
/**
* Writes back out our XSSFPictureData children
*/
* raw images associated with it.
*/
public interface XSSFChildContainingModel extends XSSFModel {
- /**
- * Find any children associated with the {@link XSSFModel}.
- * @param modelPart The PackagePart of this model
+ /**
+ * Returns the relationship type of any children we
+ * expect
+ */
+ public String[] getChildrenRelationshipTypes();
+ /**
+ * Called for each matching child, so that the
+ * appropriate model or usermodel thing can be
+ * created for it.
+ * @param childPart The PackagePart of the child
+ * @param childId the ID of the relationship the child comes from
*/
- public void findChildren(PackagePart modelPart) throws IOException, InvalidFormatException;
+ public void generateChild(PackagePart childPart, String childRelId);
+
/**
* Writes out any children associated with the {@link XSSFModel},
* along with the required relationship stuff.
import org.apache.poi.xssf.model.Drawing;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
+import org.apache.poi.xssf.model.XSSFChildContainingModel;
import org.apache.poi.xssf.model.XSSFModel;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
return null;
}
}
+
+ /**
+ * Finds all the XSSFModels of this type which are
+ * defined as relationships of the given parent part
+ */
+ public ArrayList<? extends XSSFModel> findAll(PackagePart parentPart) throws Exception {
+ ArrayList<XSSFModel> found = new ArrayList<XSSFModel>();
+ for(PackageRelationship rel : parentPart.getRelationshipsByType(REL)) {
+ PackagePart part = getTargetPart(parentPart.getPackage(), rel);
+ found.add(load(part));
+ }
+ return found;
+ }
+
/**
* Load, off the specified core part
*/
inp.close();
}
}
+
+ // Do children, if required
+ if(model instanceof XSSFChildContainingModel) {
+ XSSFChildContainingModel ccm =
+ (XSSFChildContainingModel)model;
+ for(String relType : ccm.getChildrenRelationshipTypes()) {
+ for(PackageRelationship rel : corePart.getRelationshipsByType(relType)) {
+ PackagePart childPart = getTargetPart(corePart.getPackage(), rel);
+ ccm.generateChild(childPart, rel.getId());
+ }
+ }
+ }
+
return model;
}
continue;
}
- // Get the comments for the sheet, if there are any
+ // Load child streams of the sheet
+ ArrayList<? extends XSSFModel> childModels;
CommentsSource comments = null;
- PackageRelationshipCollection commentsRel =
- part.getRelationshipsByType(SHEET_COMMENTS.REL);
- if(commentsRel != null && commentsRel.size() > 0) {
- PackagePart commentsPart =
- getTargetPart(commentsRel.getRelationship(0));
- comments = new CommentsTable(commentsPart.getInputStream());
- }
-
- // Get the drawings for the sheet, if there are any
- ArrayList<Drawing> drawings = new ArrayList<Drawing>();
- for(PackageRelationship rel : part.getRelationshipsByType(VML_DRAWINGS.REL)) {
- PackagePart drawingPart = getTargetPart(rel);
- Drawing drawing = new Drawing(drawingPart.getInputStream(), rel.getId());
- drawing.findChildren(drawingPart);
- drawings.add(drawing);
- }
-
- // Get the activeX controls for the sheet, if there are any
- ArrayList<Control> controls = new ArrayList<Control>();
- for(PackageRelationship rel : part.getRelationshipsByType(ACTIVEX_CONTROLS.REL)) {
- PackagePart controlPart = getTargetPart(rel);
- Control control = new Control(controlPart.getInputStream(), rel.getId());
- control.findChildren(controlPart);
- controls.add(control);
+ ArrayList<Drawing> drawings;
+ ArrayList<Control> controls;
+ try {
+ // Get the comments for the sheet, if there are any
+ childModels = SHEET_COMMENTS.findAll(part);
+ if(childModels.size() > 0) {
+ comments = (CommentsSource)childModels.get(0);
+ }
+
+ // Get the drawings for the sheet, if there are any
+ drawings = (ArrayList<Drawing>)VML_DRAWINGS.findAll(part);
+ // Get the activeX controls for the sheet, if there are any
+ controls = (ArrayList<Control>)ACTIVEX_CONTROLS.findAll(part);
+ } catch(Exception e) {
+ throw new RuntimeException("Unable to construct child part",e);
}
// Now create the sheet
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
);
assertNotNull(vba);
+ // And the drawing bit
+ PackagePart drw = pkg.getPart(
+ PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml")
+ );
+ assertNotNull(drw);
+
- // Save and re-open, is still there
+ // Save and re-open, both still there
Package nPkg = saveAndOpen(wb);
XSSFWorkbook nwb = new XSSFWorkbook(nPkg);
assertTrue(nwb.isMacroEnabled());
+
vba = nPkg.getPart(
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
);
assertNotNull(vba);
+ drw = nPkg.getPart(
+ PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml")
+ );
+ assertNotNull(drw);
// And again, just to be sure
nPkg = saveAndOpen(nwb);
nwb = new XSSFWorkbook(nPkg);
+ assertTrue(nwb.isMacroEnabled());
+
vba = nPkg.getPart(
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
);
assertNotNull(vba);
+ drw = nPkg.getPart(
+ PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml")
+ );
+ assertNotNull(drw);
FileOutputStream fout = new FileOutputStream("/tmp/foo.xlsm");
nwb.write(fout);