Java 如何使用ApachePOI或其他3-rd库更改ppt演示模式?

Java 如何使用ApachePOI或其他3-rd库更改ppt演示模式?,java,apache-poi,Java,Apache Poi,我一直在做一个项目,需要在“kiosk”演示模式下显示PPT文件。 在PPTX文件中,我可以像zip文件一样提取它,并重写包含“p:showPr useTimings=“0”p:present”等属性的presProps.xml,我还可以通过将“p:present”重写为“p:kiosk”来更改模式。 我刚刚发现我可以使用ApachePOI OPCPackage来实现这一点。 (例如) 然而,在PPT文件中,我不能像上面那样做。是否有任何方法可以更改PPT文件的演示模式。 或者我可以使用Apac

我一直在做一个项目,需要在“kiosk”演示模式下显示PPT文件。 在PPTX文件中,我可以像zip文件一样提取它,并重写包含“p:showPr useTimings=“0”p:present”等属性的presProps.xml,我还可以通过将“p:present”重写为“p:kiosk”来更改模式。 我刚刚发现我可以使用ApachePOI OPCPackage来实现这一点。 (例如)

然而,在PPT文件中,我不能像上面那样做。是否有任何方法可以更改PPT文件的演示模式。 或者我可以使用ApachePOI将PPT文件转换为PPTX文件,以便上面的解决方案可以工作


Thx

A
*。ppt
文件是以二进制文件格式存储的
PowerPoint
文件。这就是它的用途。入口点是

所有office二进制格式都有一个共同点,即它们都是用来描述文档的
记录
数据记录流。对于
PowerPoint
规范如下:

根据您的要求,有一个可选的设置。可以将
F-fKioskMode(1位)
设置为设置kiosk模式

DocumentContainer
可以通过使用
ApachePOI
获得。但是,
apachepoi
的支持结束了,因为
记录
SlideShowDocInfoAtom
直到现在才实现

但是使用自己的类SlideShowDocInfoAtom,它扩展了RecordAtom,我们可以实现这一点

例如:

import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.IOException;

import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordAtom;

public class HSLFSlideShowToKioskMode {

 // not really necessary, only for debug actions
 private static void hexDumpRecord(Record record) throws Exception {
  ByteArrayOutputStream out = new ByteArrayOutputStream();
  record.writeOut(out);
  out.flush();
  byte[] data = out.toByteArray();
  out.close();
  String hexDump = new java.math.BigInteger(data).toString(16);
  System.out.println(hexDump);
 }

 // method for get/set SlideShowDocInfoAtom
 private static SlideShowDocInfoAtom getSlideShowDocInfoAtom(HSLFSlideShow slideshow) throws Exception {
  SlideShowDocInfoAtom slideShowDocInfoAtomRecord = null;
  Record record = slideshow.getDocumentRecord().findFirstOfType(1025);
System.out.println(record.toString() + " type:" + record.getRecordType());
hexDumpRecord(record);
  if (record != null) { // we must not create new SlideShowDocInfoAtom
   // get present data
   ByteArrayOutputStream out = new ByteArrayOutputStream();
   record.writeOut(out);
   out.flush();
   byte[] data = out.toByteArray();
   out.close();
   // create new SlideShowDocInfoAtom from data
   slideShowDocInfoAtomRecord = new SlideShowDocInfoAtom(data);
   // replace old record with new SlideShowDocInfoAtom
   slideshow.getDocumentRecord().addChildBefore(
    slideShowDocInfoAtomRecord,
    record
   );
   slideshow.getDocumentRecord().removeChild(record);
  } else { // we must create new SlideShowDocInfoAtom
   slideShowDocInfoAtomRecord = new SlideShowDocInfoAtom();
   // add this SlideShowDocInfoAtom before EndDocumentAtom
   slideshow.getDocumentRecord().addChildBefore(
    slideShowDocInfoAtomRecord,
    slideshow.getDocumentRecord().findFirstOfType(1002) // 1002 = 0x3ea = RT_EndDocumentAtom
   );
  }
  return slideShowDocInfoAtomRecord;
 }

 public static void main(String[] args) throws Exception {

  HSLFSlideShow slideshow = new HSLFSlideShow(new FileInputStream("Presentation.ppt"));

  SlideShowDocInfoAtom slideShowDocInfoAtomRecord = getSlideShowDocInfoAtom(slideshow);
  slideShowDocInfoAtomRecord.setfKioskMode(true);
  slideShowDocInfoAtomRecord.setRestartTime(300000);
hexDumpRecord(slideShowDocInfoAtomRecord);

  FileOutputStream out = new FileOutputStream("PresentationKiosk.ppt");
  slideshow.write(out);
  out.close();
  slideshow.close();
 }

 //class SlideShowDocInfoAtom 
 //having methods for manipulating the [SlideShowDocInfoAtom](https://msdn.microsoft.com/en-us/library/dd908143.aspx)
 private static class SlideShowDocInfoAtom extends RecordAtom {

  private byte[] data;

  public SlideShowDocInfoAtom() {
   this.data = new byte[] {

    //header
    (byte)0x01, (byte)0x00, //MUST be 0x0001 (little endian)
    (byte)0x01, (byte)0x04, //MUST be 0x0401 = RT_SlideShowDocInfoAtom (little endian)
    (byte)0x50, (byte)0x00, (byte)0x00, (byte)0x00, //MUST be 0x00000050 (little endian)

    //R         //G         //B         //isRGB
    (byte)0x00, (byte)0xFF, (byte)0x00, (byte)0xFE, //penColor green

    (byte)0xe0, (byte)0x93, (byte)0x04, (byte)0x00, //restartTime 300000 ms (0x493e0, little endian)

    (byte)0x00, (byte)0x00, //startSlide, only if fUseSlideRange is set

    (byte)0x00, (byte)0x00, //endSlide, only if fUseSlideRange is set

    //namedShow (64 bytes), only filled if there are named shows and fDocUseNamedShow is set, else all 0x00
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //8
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //16
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //24
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //32
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //40
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //48
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //56
    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //64

    //H                 G                  F          E           D                C              B               A
    //fLoopContinuously,fWillSkipNarration,fKioskMode,fBrowseMode,fDocUseNamedShow,fUseSlideRange,fWillSkipBuilds,fAutoAdvance
    (byte)Integer.parseInt("00010000", 2), //only fBrowseMode is set

    //              I
    //0,0,0,0,0,0,0,fHideScrollBar
    (byte)Integer.parseInt("00000000", 2),

    (byte)0x00, (byte)0x00 //unused

   };
  }

  public SlideShowDocInfoAtom(byte[] data) {
   this.data = data;
  }

  public void setfKioskMode(boolean on) {
   byte HGFEDCBA = this.data[84];
   HGFEDCBA &= (byte)Integer.parseInt("110011111", 2); //fKioskMode and fBrowseMode = 0
   if (on) HGFEDCBA |= (byte)Integer.parseInt("10100000", 2); //fLoopContinuously = 1 and fKioskMode = 1
   else HGFEDCBA |= (byte)Integer.parseInt("00010000", 2); //fBrowseMode = 1
   this.data[84] = HGFEDCBA;
  }

  public void setRestartTime(long milliseconds) {
   //must be greater than or equal 300000
   if (milliseconds < 300000) return;
   this.data[12] = (byte) (milliseconds & 0xFF);
   this.data[13] = (byte) ((milliseconds >> 8) & 0xFF);
   this.data[14] = (byte) ((milliseconds >> 16) & 0xFF);
   this.data[15] = (byte) ((milliseconds >> 24) & 0xFF);
  }

  //TODO: other setters

  @Override
  public void writeOut(OutputStream out) throws IOException {
   out.write(data);
  }

  @Override
  public long getRecordType() { return 1025; }
 }

}
import java.io.FileOutputStream;
导入java.io.FileInputStream;
导入java.io.ByteArrayOutputStream;
导入java.io.OutputStream;
导入java.io.IOException;
导入org.apache.poi.hslf.usermodel.*;
导入org.apache.poi.hslf.record.record;
导入org.apache.poi.hslf.record.RecordAtom;
公共类HSLFSlideShowToKioskMode{
//不需要,仅用于调试操作
私有静态无效hexDumpRecord(记录记录)引发异常{
ByteArrayOutputStream out=新建ByteArrayOutputStream();
记录.注销(出);
out.flush();
字节[]数据=out.toByteArray();
out.close();
字符串hextump=newjava.math.biginger(data.toString)(16);
System.out.println(hextump);
}
//获取/设置SlideShowDocInfoAtom的方法
私有静态SlideShowDocInfoAtom getSlideShowDocInfoAtom(HSLFSlideShow slideshow)引发异常{
SlideShowDocInfoAtom slideShowDocInfoAtomRecord=null;
Record Record=slideshow.getDocumentRecord().findFirstOfType(1025);
System.out.println(record.toString()+”类型:“+record.getRecordType());
记录(记录);
如果(record!=null){//我们不能创建新的SlideShowDocInfoAtom
//获取当前数据
ByteArrayOutputStream out=新建ByteArrayOutputStream();
记录.注销(出);
out.flush();
字节[]数据=out.toByteArray();
out.close();
//从数据创建新的SlideShowDocInfoAtom
slideShowDocInfoAtomRecord=新的SlideShowDocInfoAtom(数据);
//用新的SlideShowDocInfoAtom替换旧记录
slideshow.getDocumentRecord().addChildBefore(
幻灯片放映DocInfoAtomRecord,
记录
);
slideshow.getDocumentRecord().removeChild(记录);
}否则{//我们必须创建新的SlideShowDocInfoAtom
slideShowDocInfoAtomRecord=新的SlideShowDocInfoAtom();
//在EndDocumentTom之前添加此幻灯片ShowDocInfoAtom
slideshow.getDocumentRecord().addChildBefore(
幻灯片放映DocInfoAtomRecord,
slideshow.getDocumentRecord().findFirstOfType(1002)//1002=0x3ea=RT\u endDocumentTom
);
}
返回幻灯片howdocinfoatomrecord;
}
公共静态void main(字符串[]args)引发异常{
HSLFSlideShow slideshow=新的HSLFSlideShow(新文件输入流(“Presentation.ppt”);
SlideShowDocInfoAtom slideShowDocInfoAtomRecord=getSlideShowDocInfoAtom(slideshow);
slideShowDocInfoAtomRecord.setfKioskMode(true);
slideShowDocInfoAtomRecord.setRestartTime(300000);
hexDumpRecord(slideShowDocInfoAtomRecord);
FileOutputStream out=新的FileOutputStream(“PresentationKiosk.ppt”);
幻灯片。写出来;
out.close();
slideshow.close();
}
//类SlideShowDocInfoAtom
//具有操作[SlideShowDocInfoAtom]的方法(https://msdn.microsoft.com/en-us/library/dd908143.aspx)
私有静态类SlideShowDocInfoAtom扩展了RecordAtom{
专用字节[]数据;
公共幻灯片howDocInfoAtom(){
this.data=新字节[]{
//标题
(字节)0x01,(字节)0x00,//必须是0x0001(小端)
(字节)0x01,(字节)0x04,//必须是0x0401=RT\u SlideShowDocInfoAtom(小端)
(字节)0x50,(字节)0x00,(字节)0x00,(字节)0x00,//必须是0x00000050(小端)
//R//G//B//isRGB
(字节)0x00,(字节)0xFF,(字节)0x00,(字节)0xFE,//彩色绿色
(字节)0xe0,(字节)0x93,(字节)0x04,(字节)0x00,//重启时间300000毫秒(0x493e0,小端)
(字节)0x00,(字节)0x00,//仅当设置了fUseSlideRange时才开始滑动
(字节)0x00,(字节)0x00,//endSlide,仅当设置了fUseSlideRange时
//namedShow(64字节),仅在有命名节目且设置了fDocUseNamedShow时填写,否则全部为0x00
(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,//8
(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,//16
(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,//24
(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,//32
(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,//40
(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,//48
(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,//56
(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,//64
//H