- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想使用 apache poi 将 excel 表嵌入到演示文稿 (PPT) 中。我们应该怎么做?如果有人知道,请帮助我。
最佳答案
我花了一段时间才弄清楚这些部分是如何组合在一起的......
嵌入可以通过两种方式完成:
ObjectData.get/setData()
即可完成像往常一样,当我试图找出如何实现某些 POI 功能时,我将结果与 Libre Office 文件进行比较,在这种情况下,必须创建/修改一些部分:
Document
中嵌入记录来引用记录此外,我还使用了两个实用的信息类:BiffViewer
和 POIFSLister
.
由于这只是概念验证,因此远未完成。有关嵌入元素表示的进一步修改,您需要咨询 the spec .
为嵌入对象创建预览图像仍有一个 Unresolved 问题。您可能想要使用中性图像,只要用户激活(双击)ole 对象,它就会被替换......另一种方法是使用 jodconverter , 但比起 POI 方法会有点无意义......
(使用 POI3.9/Libre Office 4.0/MS Excel Viewer/MS Office 2003 测试)
import java.awt.geom.Rectangle2D;
import java.io.*;
import java.lang.reflect.Field;
import org.apache.poi.POIDocument;
import org.apache.poi.ddf.*;
import org.apache.poi.hpsf.ClassID;
import org.apache.poi.hslf.HSLFSlideShow;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.model.*;
import org.apache.poi.hslf.model.Picture;
import org.apache.poi.hslf.model.Slide;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.*;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.util.*;
public class PoiOleXlsInPpt {
static final OleType EXCEL97 = new OleType("{00020820-0000-0000-C000-000000000046}");
static final OleType EXCEL95 = new OleType("{00020810-0000-0000-C000-000000000046}");
static final OleType WORD97 = new OleType("{00020906-0000-0000-C000-000000000046}");
static final OleType WORD95 = new OleType("{00020900-0000-0000-C000-000000000046}");
static final OleType POWERPOINT97 = new OleType("{64818D10-4F9B-11CF-86EA-00AA00B929E8}");
static final OleType POWERPOINT95 = new OleType("{EA7BAE70-FB3B-11CD-A903-00AA00510EA3}");
static class OleType {
final String classId;
OleType(String classId) {
this.classId = classId;
}
ClassID getClassID() {
ClassID cls = new ClassID();
byte clsBytes[] = cls.getBytes();
String clsStr = classId.replaceAll("[{}-]", "");
for (int i=0; i<clsStr.length(); i+=2) {
clsBytes[i/2] = (byte)Integer.parseInt(clsStr.substring(i, i+2), 16);
}
return cls;
}
}
public static void main(String[] args) throws Exception {
HSLFSlideShow _hslfSlideShow = HSLFSlideShow.create();
SlideShow ppt = new SlideShow(_hslfSlideShow);
OLEShape oleShape1 = createOLEShape(getSampleWorkbook1(), ppt, _hslfSlideShow, EXCEL97);
oleShape1.setAnchor(new Rectangle2D.Double(100,100,100,100));
OLEShape oleShape2 = createOLEShape(getSampleWorkbook2(), ppt, _hslfSlideShow, EXCEL97);
oleShape2.setAnchor(new Rectangle2D.Double(300,300,100,100));
OLEShape oleShape3 = createOLEShape(getSampleDocument(), ppt, _hslfSlideShow, WORD97);
oleShape3.setAnchor(new Rectangle2D.Double(300,100,100,100));
// create and link visuals to the ole data
Slide slide = ppt.createSlide();
slide.addShape(oleShape1);
slide.addShape(oleShape2);
slide.addShape(oleShape3);
FileOutputStream fos = new FileOutputStream("ole_xls_in_ppt_out2.ppt");
ppt.write(fos);
fos.close();
}
static OLEShape createOLEShape(
POIDocument sample
, SlideShow ppt
, HSLFSlideShow _hslfSlideShow
, OleType oleType
) throws IOException {
// generate a preview image
int prevIdx = generatePreview(ppt, sample);
// add the data to the SlideShow
ExEmbed eeEmbed = addOleDataToDocumentRecord(ppt);
ExOleObjStg exOleObjStg = addOleDataToRootRecords(_hslfSlideShow, sample, oleType);
eeEmbed.getExOleObjAtom().setObjStgDataRef(exOleObjStg.getPersistId());
OLEShape oleShape = new OLEShape(prevIdx);
linkOleDataToShape(oleShape, eeEmbed);
return oleShape;
}
static POIDocument getSampleWorkbook1() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
sheet.createRow(1).createCell(1).setCellValue("First Workbook");
return wb;
}
static POIDocument getSampleWorkbook2() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
sheet.createRow(1).createCell(1).setCellValue("Second Workbook");
return wb;
}
// the sample document has apparently a problem,
// i.e. word inside ms powerpoint crashed, and libre office doesn't display the text
// it was just a test, if embedding elements != Excel works
// in case HWPF is interesting to you, you probably know anyway, where the error below is ...
static POIDocument getSampleDocument() throws IOException {
FileInputStream fis = new FileInputStream("src/test/resources/empty.doc");
HWPFDocument doc = new HWPFDocument(fis);
fis.close();
Range range = doc.getRange();
CharacterRun run1 = range.insertAfter("Sample text");
run1.setFontSize(11);
return doc;
}
/**
* Generates a modified version of the sample element, which
* contains embedding informations
*/
static byte[] wrapOleData(POIDocument oleData, OleType oleType) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
oleData.write(bos);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
bos.reset();
POIFSFileSystem poifs = new POIFSFileSystem(bis);
final String OLESTREAM_NAME = "\u0001Ole";
DirectoryNode root = poifs.getRoot();
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 };
poifs.createDocument(new ByteArrayInputStream(oleBytes), OLESTREAM_NAME);
}
// need to set storage clsid, otherwise embedded object is not recognized
root.setStorageClsid(oleType.getClassID());
poifs.writeFilesystem(bos);
return bos.toByteArray();
} catch (IOException e) {
throw new RuntimeException("wth?!", e);
}
}
/**
* to be defined, how to create a preview image
* for a start, I've taken just a dummy image, which will be
* replaced, when the user activates the ole object
*
* not really an alternativ:
* http://stackoverflow.com/questions/16704624/how-to-print-a-workbook-file-made-using-apache-poi-and-java
*
* @return image index of the preview image
*/
static int generatePreview(SlideShow ppt, POIDocument oleData) {
try {
FileInputStream fis = new FileInputStream("src/test/resources/dilbert-2011-09-28-powerpoint.jpg");
byte previewImg[] = IOUtils.toByteArray(fis);
fis.close();
return ppt.addPicture(previewImg, Picture.JPEG);
} catch (IOException e) {
throw new RuntimeException("not really?", e);
}
}
static ExEmbed addOleDataToDocumentRecord(SlideShow ppt) {
// taken from SlideShow.addControl()
Document _documentRecord = ppt.getDocumentRecord();
ExObjList lst = _documentRecord.getExObjList();
if (lst == null) {
lst = new ExObjList();
_documentRecord.addChildAfter(lst, _documentRecord.getDocumentAtom());
try {
Field f = Document.class.getDeclaredField("exObjList");
f.setAccessible(true);
f.set(_documentRecord, lst);
} catch (Exception e) {
throw new RuntimeException("not here", e);
}
}
ExObjListAtom objAtom = lst.getExObjListAtom();
// increment the object ID seed
int objectId = (int) objAtom.getObjectIDSeed() + 1;
objAtom.setObjectIDSeed(objectId);
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();
try {
Field f = ExEmbedAtom.class.getDeclaredField("_data");
f.setAccessible(true);
f.set(eeEmbed, new byte[]{0,0,0,0,1/*CantLockServerB*/,0,0,0});
// oops, there seems to be an error in the default constructor ...
// should be 8 and not 7 bytes
setRecordLength(eeEmbed, 8);
} catch (Exception e) {
throw new RuntimeException("trust me ;)", e);
}
ExOleObjAtom eeAtom = exEmbed.getExOleObjAtom();
eeAtom.setObjID(objectId);
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);
lst.addChildAfter(exEmbed, objAtom);
return exEmbed;
}
static ExOleObjStg addOleDataToRootRecords(
HSLFSlideShow _hslfSlideShow
, POIDocument oleData
, OleType oleType
) throws IOException {
ExOleObjStg exOleObjStg = new ExOleObjStg();
int slideRecordPos = _hslfSlideShow.appendRootLevelRecord(exOleObjStg);
exOleObjStg.setPersistId(slideRecordPos);
exOleObjStg.setData(wrapOleData(oleData, oleType));
// taken from SlideShow.createSlide
Record _records[] = _hslfSlideShow.getRecords();
// Add the new OLE record into the PersistPtr stuff
int offset = 0;
int slideOffset = 0;
PersistPtrHolder ptr = null;
UserEditAtom usr = null;
for (int i = 0; i < _records.length; i++) {
Record record = _records[i];
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
record.writeOut(out);
} catch (IOException e) {
throw new HSLFException(e);
}
// Grab interesting records as they come past
if (_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID) {
ptr = (PersistPtrHolder) _records[i];
}
if (_records[i].getRecordType() == RecordTypes.UserEditAtom.typeID) {
usr = (UserEditAtom) _records[i];
}
if (i == slideRecordPos) {
slideOffset = offset;
}
offset += out.size();
}
// the ole objects needs to know its position within
// the root records, because it will be later accessed
// via its index from the shape
int psrId = usr.getMaxPersistWritten() + 1;
exOleObjStg.setPersistId(psrId);
// Last view is now of the slide
usr.setLastViewType((short) UserEditAtom.LAST_VIEW_SLIDE_VIEW);
usr.setMaxPersistWritten(psrId); // increment the number of persit objects
// Add the new slide into the last PersistPtr
// (Also need to tell it where it is)
exOleObjStg.setLastOnDiskOffset(slideOffset);
ptr.addSlideLookup(psrId, slideOffset);
return exOleObjStg;
}
static void linkOleDataToShape(OLEShape oleShape, ExEmbed exEmbed) {
oleShape.setEscherProperty(EscherProperties.BLIP__PICTUREID, exEmbed.getExOleObjAtom().getObjID());
EscherSpRecord spRecord = oleShape.getSpContainer().getChildById(EscherSpRecord.RECORD_ID);
spRecord.setFlags(spRecord.getFlags()|EscherSpRecord.FLAG_OLESHAPE);
// ExObjRefAtom is not set in OLEShape
UnknownEscherRecord uer = new UnknownEscherRecord();
byte uerData[] = new byte[12];
LittleEndian.putShort( uerData, 0, (short)0 ); // options = 0
LittleEndian.putShort( uerData, 2, (short)RecordTypes.ExObjRefAtom.typeID); // recordId
LittleEndian.putInt( uerData, 4, 4 ); // remaining bytes
LittleEndian.putInt( uerData, 8, exEmbed.getExOleObjAtom().getObjID() ); // the data
uer.fillFields(uerData, 0, null);
EscherContainerRecord uerCont = new EscherContainerRecord();
uerCont.setRecordId((short)RecordTypes.EscherClientData);
uerCont.setVersion((short)0x000F); // yes, we are still a container ...
uerCont.addChildRecord(uer);
oleShape.getSpContainer().addChildRecord(uerCont);
}
static void setRecordLength(Record record, int len) throws NoSuchFieldException, IllegalAccessException {
Field f = record.getClass().getDeclaredField("_header");
f.setAccessible(true);
byte _header[] = (byte[])f.get(record);
LittleEndian.putInt(_header, 4, len);
f.set(record, _header);
}
}
关于java - 使用 apache poi 将 HSSF(excel) 嵌入到 HSLF(ppt) 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2849102/
我需要像这样从api下载一个文件 http://52.76.226.179/aapc-social-web/sites/default/files/media_docs/2009/content-60
如果我编写并执行这段代码 from pptx import Presentation prs = Presentation() slide_layout = prs.slide_layouts[0]
我希望 VBA 将所有工作表粘贴到示例 PPT 中,该示例从特定幻灯片开始,例如幻灯片 NUM.3 但是现在正在使用的代码,不要将所选区域粘贴到 PPT 文件中。你可以帮帮我吗? 这是我的代码:
我正在 office powerpoint(2007、2010 和 2013 版本)上做一些开发工作,并寻找一个将在 PowerPoint 幻灯片中调整对象(如文本框)大小时触发的事件。我想在用 C#
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic
我在页面上有以下脚本,用于将用户重定向到选定的二进制项目(doc、docx、ppt、pptx、xls、xlsx)。 $(document).ready(function () { window
这在 javascript 注入(inject)下算作,但我还是想问一下,以防万一人们知道答案。 我有一个网页,在让您进入下一页之前,该网页会倒计时至零。我有一个脚本,它将检查它何时为 0,然后单击
我正在使用 aspose-slides-17.3-jdk16.jar for java。我想自定义 PPT 中幻灯片的页面设置。 任何帮助将不胜感激。 最佳答案 我观察到您使用 Aspose.Slid
我正在尝试打开已存储在应用程序数据目录中的 pptx 文件,但打开该 ppt 文件时遇到错误。 我使用基本方法获取文件路径,然后获取 Uri,从那里将文件 Uri 传递给打开 pptx 文件的 Int
我正在编写一个将 PPT 文件中的幻灯片转换为 png 的小工具,我遇到的问题是隐藏的幻灯片。如何将幻灯片更改为在 Java 中可见?我目前正在使用 Apache POI 转换为 PNG,尽管这不适用
我正在尝试以编程方式生成一个 ppt,它基本上会有多张带有图像和文本的幻灯片。我试着寻找它,但没有找到任何方法,但我发现有几个应用程序可以这样做 PDF to PowerPoint 和 PDF to
我想用我的应用程序打开一个 PPT 文件。如何检查设备上是否安装了可以显示这些文件的应用程序以及如何启动它? 最佳答案 尝试这样的事情。没试过但可能有用 final Uri uri = Uri.fro
在PPT Presentation中,有一个Rise up的选项。在该选项中,对象首先向上移动,减速,然后返回,最后停止。动画效果链接: 我们如何在 CSS 中实现它? img { height:
我正在尝试使用 C# 将 .ppt 文件转换为图像集合。 我正在使用以下代码: using Microsoft.Office.Core; using Microsoft.Office.Interop.
我目前正在尝试从 .ppt 和 .pptx 文件中提取文本。我成功地使用 python-pptx 来处理 .pptx 文件,但是根据 its documentation , "PowerPoint 2
包含 .pdf 的链接将在新选项卡中打开,如下所示: Download 是否可以让 Powerpoint 文件 .ppt 在新的浏览器选项卡中打开而不是让用户下载该文件? 我已经尝试了以下操作,但这会
我想知道是否可以将“幻灯片大小为”设置为屏幕显示 (16:9)。我的意思是在 apache poi hslf 的主对象中有任何方法吗?我找不到。我已添加图像以供引用。 最佳答案 您只能拥有一个 pag
我在这里找到了一个函数,可以为在 R 中创建的绘图创建一个带有幻灯片的 ppt。 这是该函数的链接:R: Function to export currently active R plot to P
是否可以使用 将 odp/ppt 幻灯片导出为图像unoconv ? 例如, unoconv -f png presentation.ppt 但是这个 unoconv 命令会转换 只有第一张幻灯片 作
我有通过我无法控制的软件生成的 PPT。生成后,该软件将所有文本放入 TextBoxes 而不是我的占位符。 我创建了一个脚本来将文本从 TextBoxes 移动到占位符中,这很好用;但是,我无法维护
我是一名优秀的程序员,十分优秀!