protected HSSFWorkbook makeWorkbook(final Report report, final ELContext ctx) throws Exception { final byte[] emptyWorkbookData = new HSSFWorkbook().getBytes(); final POIFSFileSystem fs; if (report.getTemplate() != null) { fs = new POIFSFileSystem(new ByteArrayInputStream(report.getTemplate())); } else { fs = new POIFSFileSystem(); fs.createDocument(new ByteArrayInputStream(emptyWorkbookData), "Workbook"); } final MutablePropertySet siProperties = new MutablePropertySet(); final MutableSection siSection = (MutableSection) siProperties.getSections().get(0); siSection.setFormatID(SectionIDMap.SUMMARY_INFORMATION_ID); final MutableProperty p0 = new MutableProperty(); p0.setID(PropertyIDMap.PID_CREATE_DTM); p0.setType(Variant.VT_FILETIME); p0.setValue(new Date()); siSection.setProperty(p0); final String application = report.getDescription().getApplication(ctx); if (application != null) { final MutableProperty p = new MutableProperty(); p.setID(PropertyIDMap.PID_APPNAME); p.setType(Variant.VT_LPWSTR); p.setValue(application); siSection.setProperty(p); } final String author = report.getDescription().getAuthor(ctx); if (author != null) { final MutableProperty p = new MutableProperty(); p.setID(PropertyIDMap.PID_AUTHOR); p.setType(Variant.VT_LPWSTR); p.setValue(author); siSection.setProperty(p); } final String version = report.getDescription().getVersion(ctx); if (version != null) { final MutableProperty p = new MutableProperty(); p.setID(PropertyIDMap.PID_REVNUMBER); p.setType(Variant.VT_LPWSTR); p.setValue(version); siSection.setProperty(p); } final String title = report.getDescription().getTitle(ctx); if (title != null) { final MutableProperty p = new MutableProperty(); p.setID(PropertyIDMap.PID_TITLE); p.setType(Variant.VT_LPWSTR); p.setValue(title); siSection.setProperty(p); } final String subject = report.getDescription().getSubject(ctx); if (subject != null) { final MutableProperty p = new MutableProperty(); p.setID(PropertyIDMap.PID_SUBJECT); p.setType(Variant.VT_LPWSTR); p.setValue(subject); siSection.setProperty(p); } final String comments = report.getDescription().getComments(ctx); if (comments != null) { final MutableProperty p = new MutableProperty(); p.setID(PropertyIDMap.PID_COMMENTS); p.setType(Variant.VT_LPWSTR); p.setValue(comments); siSection.setProperty(p); } final MutablePropertySet dsiProperties = new MutablePropertySet(); final MutableSection dsiSection = (MutableSection) dsiProperties.getSections().get(0); dsiSection.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]); final String company = report.getDescription().getCompany(ctx); if (company != null) { final MutableProperty p = new MutableProperty(); p.setID(PropertyIDMap.PID_COMPANY); p.setType(Variant.VT_LPWSTR); p.setValue(company); dsiSection.setProperty(p); } final String category = report.getDescription().getCategory(ctx); if (category != null) { final MutableProperty p = new MutableProperty(); p.setID(PropertyIDMap.PID_CATEGORY); p.setType(Variant.VT_LPWSTR); p.setValue(category); dsiSection.setProperty(p); } fs.createDocument(siProperties.toInputStream(), SummaryInformation.DEFAULT_STREAM_NAME); fs.createDocument( dsiProperties.toInputStream(), DocumentSummaryInformation.DEFAULT_STREAM_NAME); return new HSSFWorkbook(fs, true); }
/** * Add a embedded object to this presentation * * @return 0-based index of the embedded object */ public int addEmbed(POIFSFileSystem poiData) { DirectoryNode root = poiData.getRoot(); // prepare embedded data if (new ClassID().equals(root.getStorageClsid())) { // need to set class id Map<String, ClassID> olemap = getOleMap(); ClassID classID = null; for (Map.Entry<String, ClassID> entry : olemap.entrySet()) { if (root.hasEntry(entry.getKey())) { classID = entry.getValue(); break; } } if (classID == null) { throw new IllegalArgumentException("Unsupported embedded document"); } root.setStorageClsid(classID); } ExEmbed exEmbed = new ExEmbed(); // remove unneccessary infos, so we don't need to specify the type // of the ole object multiple times Record children[] = exEmbed.getChildRecords(); exEmbed.removeChild(children[2]); exEmbed.removeChild(children[3]); exEmbed.removeChild(children[4]); ExEmbedAtom eeEmbed = exEmbed.getExEmbedAtom(); eeEmbed.setCantLockServerB(true); ExOleObjAtom eeAtom = exEmbed.getExOleObjAtom(); eeAtom.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); eeAtom.setType(ExOleObjAtom.TYPE_EMBEDDED); // eeAtom.setSubType(ExOleObjAtom.SUBTYPE_EXCEL); // should be ignored?!?, see MS-PPT ExOleObjAtom, but Libre Office sets it ... eeAtom.setOptions(1226240); ExOleObjStg exOleObjStg = new ExOleObjStg(); try { final String OLESTREAM_NAME = "\u0001Ole"; if (!root.hasEntry(OLESTREAM_NAME)) { // the following data was taken from an example libre office document // beside this "\u0001Ole" record there were several other records, e.g. CompObj, // OlePresXXX, but it seems, that they aren't neccessary byte oleBytes[] = {1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; poiData.createDocument(new ByteArrayInputStream(oleBytes), OLESTREAM_NAME); } ByteArrayOutputStream bos = new ByteArrayOutputStream(); poiData.writeFilesystem(bos); exOleObjStg.setData(bos.toByteArray()); } catch (IOException e) { throw new HSLFException(e); } int psrId = addPersistentObject(exOleObjStg); exOleObjStg.setPersistId(psrId); eeAtom.setObjStgDataRef(psrId); int objectId = addToObjListAtom(exEmbed); eeAtom.setObjID(objectId); return objectId; }
/** * Writes out the word file that is represented by an instance of this class. * * @param out The OutputStream to write to. * @throws IOException If there is an unexpected IOException from the passed in OutputStream. */ public void write(OutputStream out) throws IOException { // initialize our streams for writing. HWPFFileSystem docSys = new HWPFFileSystem(); HWPFOutputStream wordDocumentStream = docSys.getStream(STREAM_WORD_DOCUMENT); HWPFOutputStream tableStream = docSys.getStream(STREAM_TABLE_1); // HWPFOutputStream dataStream = docSys.getStream("Data"); int tableOffset = 0; // FileInformationBlock fib = (FileInformationBlock)_fib.clone(); // clear the offsets and sizes in our FileInformationBlock. _fib.clearOffsetsSizes(); // determine the FileInformationBLock size int fibSize = _fib.getSize(); fibSize += POIFSConstants.SMALLER_BIG_BLOCK_SIZE - (fibSize % POIFSConstants.SMALLER_BIG_BLOCK_SIZE); // preserve space for the FileInformationBlock because we will be writing // it after we write everything else. byte[] placeHolder = new byte[fibSize]; wordDocumentStream.write(placeHolder); int mainOffset = wordDocumentStream.getOffset(); // write out the StyleSheet. _fib.setFcStshf(tableOffset); _ss.writeTo(tableStream); _fib.setLcbStshf(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); // get fcMin and fcMac because we will be writing the actual text with the // complex table. int fcMin = mainOffset; /* * clx (encoding of the sprm lists for a complex file and piece table * for a any file) Written immediately after the end of the previously * recorded structure. This is recorded in all Word documents * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 23 of 210 */ // write out the Complex table, includes text. _fib.setFcClx(tableOffset); _cft.writeTo(wordDocumentStream, tableStream); _fib.setLcbClx(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); int fcMac = wordDocumentStream.getOffset(); /* * dop (document properties record) Written immediately after the end of * the previously recorded structure. This is recorded in all Word * documents * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 23 of 210 */ // write out the DocumentProperties. _fib.setFcDop(tableOffset); _dop.writeTo(tableStream); _fib.setLcbDop(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); /* * plcfBkmkf (table recording beginning CPs of bookmarks) Written * immediately after the sttbfBkmk, if the document contains bookmarks. * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 24 of 210 */ if (_bookmarksTables != null) { _bookmarksTables.writePlcfBkmkf(_fib, tableStream); tableOffset = tableStream.getOffset(); } /* * plcfBkmkl (table recording limit CPs of bookmarks) Written * immediately after the plcfBkmkf, if the document contains bookmarks. * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 24 of 210 */ if (_bookmarksTables != null) { _bookmarksTables.writePlcfBkmkl(_fib, tableStream); tableOffset = tableStream.getOffset(); } /* * plcfbteChpx (bin table for CHP FKPs) Written immediately after the * previously recorded table. This is recorded in all Word documents. * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 24 of 210 */ // write out the CHPBinTable. _fib.setFcPlcfbteChpx(tableOffset); _cbt.writeTo(wordDocumentStream, tableStream, fcMin, _cft.getTextPieceTable()); _fib.setLcbPlcfbteChpx(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); /* * plcfbtePapx (bin table for PAP FKPs) Written immediately after the * plcfbteChpx. This is recorded in all Word documents. * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 24 of 210 */ // write out the PAPBinTable. _fib.setFcPlcfbtePapx(tableOffset); _pbt.writeTo(wordDocumentStream, tableStream, _cft.getTextPieceTable()); _fib.setLcbPlcfbtePapx(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); /* * plcfendRef (endnote reference position table) Written immediately * after the previously recorded table if the document contains endnotes * * plcfendTxt (endnote text position table) Written immediately after * the plcfendRef if the document contains endnotes * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 24 of 210 */ _endnotesTables.writeRef(_fib, tableStream); _endnotesTables.writeTxt(_fib, tableStream); tableOffset = tableStream.getOffset(); /* * plcffld*** (table of field positions and statuses for annotation * subdocument) Written immediately after the previously recorded table, * if the ******* subdocument contains fields. * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 24 of 210 */ if (_fieldsTables != null) { _fieldsTables.write(_fib, tableStream); tableOffset = tableStream.getOffset(); } /* * plcffndRef (footnote reference position table) Written immediately * after the stsh if the document contains footnotes * * plcffndTxt (footnote text position table) Written immediately after * the plcffndRef if the document contains footnotes * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 24 of 210 */ _footnotesTables.writeRef(_fib, tableStream); _footnotesTables.writeTxt(_fib, tableStream); tableOffset = tableStream.getOffset(); /* * plcfsed (section table) Written immediately after the previously * recorded table. Recorded in all Word documents * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 25 of 210 */ // write out the SectionTable. _fib.setFcPlcfsed(tableOffset); _st.writeTo(wordDocumentStream, tableStream); _fib.setLcbPlcfsed(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); // write out the list tables if (_lt != null) { /* * plcflst (list formats) Written immediately after the end of the * previously recorded, if there are any lists defined in the * document. This begins with a short count of LSTF structures * followed by those LSTF structures. This is immediately followed * by the allocated data hanging off the LSTFs. This data consists * of the array of LVLs for each LSTF. (Each LVL consists of an LVLF * followed by two grpprls and an XST.) * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 25 of 210 */ _lt.writeListDataTo(_fib, tableStream); tableOffset = tableStream.getOffset(); /* * plflfo (more list formats) Written immediately after the end of * the plcflst and its accompanying data, if there are any lists * defined in the document. This consists first of a PL of LFO * records, followed by the allocated data (if any) hanging off the * LFOs. The allocated data consists of the array of LFOLVLFs for * each LFO (and each LFOLVLF is immediately followed by some LVLs). * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 26 of 210 */ _fib.setFcPlfLfo(tableStream.getOffset()); _lt.writeListOverridesTo(tableStream); _fib.setLcbPlfLfo(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); } /* * sttbfBkmk (table of bookmark name strings) Written immediately after * the previously recorded table, if the document contains bookmarks. * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 27 of 210 */ if (_bookmarksTables != null) { _bookmarksTables.writeSttbfBkmk(_fib, tableStream); tableOffset = tableStream.getOffset(); } /* * sttbSavedBy (last saved by string table) Written immediately after * the previously recorded table. * * Microsoft Office Word 97-2007 Binary File Format (.doc) * Specification; Page 27 of 210 */ // write out the saved-by table. if (_sbt != null) { _fib.setFcSttbSavedBy(tableOffset); _sbt.writeTo(tableStream); _fib.setLcbSttbSavedBy(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); } // write out the revision mark authors table. if (_rmat != null) { _fib.setFcSttbfRMark(tableOffset); _rmat.writeTo(tableStream); _fib.setLcbSttbfRMark(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); } // write out the FontTable. _fib.setFcSttbfffn(tableOffset); _ft.writeTo(tableStream); _fib.setLcbSttbfffn(tableStream.getOffset() - tableOffset); tableOffset = tableStream.getOffset(); // set some variables in the FileInformationBlock. _fib.getFibBase().setFcMin(fcMin); _fib.getFibBase().setFcMac(fcMac); _fib.setCbMac(wordDocumentStream.getOffset()); // make sure that the table, doc and data streams use big blocks. byte[] mainBuf = wordDocumentStream.toByteArray(); if (mainBuf.length < 4096) { byte[] tempBuf = new byte[4096]; System.arraycopy(mainBuf, 0, tempBuf, 0, mainBuf.length); mainBuf = tempBuf; } // Table1 stream will be used _fib.getFibBase().setFWhichTblStm(true); // write out the FileInformationBlock. // _fib.serialize(mainBuf, 0); _fib.writeTo(mainBuf, tableStream); byte[] tableBuf = tableStream.toByteArray(); if (tableBuf.length < 4096) { byte[] tempBuf = new byte[4096]; System.arraycopy(tableBuf, 0, tempBuf, 0, tableBuf.length); tableBuf = tempBuf; } byte[] dataBuf = _dataStream; if (dataBuf == null) { dataBuf = new byte[4096]; } if (dataBuf.length < 4096) { byte[] tempBuf = new byte[4096]; System.arraycopy(dataBuf, 0, tempBuf, 0, dataBuf.length); dataBuf = tempBuf; } // create new document preserving order of entries POIFSFileSystem pfs = new POIFSFileSystem(); boolean docWritten = false; boolean dataWritten = false; boolean objectPoolWritten = false; boolean tableWritten = false; boolean propertiesWritten = false; for (Iterator<Entry> iter = directory.getEntries(); iter.hasNext(); ) { Entry entry = iter.next(); if (entry.getName().equals(STREAM_WORD_DOCUMENT)) { if (!docWritten) { pfs.createDocument(new ByteArrayInputStream(mainBuf), STREAM_WORD_DOCUMENT); docWritten = true; } } else if (entry.getName().equals(STREAM_OBJECT_POOL)) { if (!objectPoolWritten) { _objectPool.writeTo(pfs.getRoot()); objectPoolWritten = true; } } else if (entry.getName().equals(STREAM_TABLE_0) || entry.getName().equals(STREAM_TABLE_1)) { if (!tableWritten) { pfs.createDocument(new ByteArrayInputStream(tableBuf), STREAM_TABLE_1); tableWritten = true; } } else if (entry.getName().equals(SummaryInformation.DEFAULT_STREAM_NAME) || entry.getName().equals(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) { if (!propertiesWritten) { writeProperties(pfs); propertiesWritten = true; } } else if (entry.getName().equals(STREAM_DATA)) { if (!dataWritten) { pfs.createDocument(new ByteArrayInputStream(dataBuf), STREAM_DATA); dataWritten = true; } } else { EntryUtils.copyNodeRecursively(entry, pfs.getRoot()); } } if (!docWritten) pfs.createDocument(new ByteArrayInputStream(mainBuf), STREAM_WORD_DOCUMENT); if (!tableWritten) pfs.createDocument(new ByteArrayInputStream(tableBuf), STREAM_TABLE_1); if (!propertiesWritten) writeProperties(pfs); if (!dataWritten) pfs.createDocument(new ByteArrayInputStream(dataBuf), STREAM_DATA); if (!objectPoolWritten) _objectPool.writeTo(pfs.getRoot()); pfs.writeFilesystem(out); this.directory = pfs.getRoot(); /* * since we updated all references in FIB and etc, using new arrays to * access data */ this.directory = pfs.getRoot(); this._tableStream = tableStream.toByteArray(); this._dataStream = dataBuf; }