简体   繁体   English

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

[英]How to change ppt presentation mode using apache-poi or another 3-rd library?

I've been working on a project which needs to display a PPT file in "kiosk" presentation mode. 我一直在从事一个需要以“信息亭”演示模式显示PPT文件的项目。 In a PPTX file, I can extract it like a zip file and rewrite the presProps.xml which contains properties like "p:showPr useTimings="0" p:present", and I can change the mode by rewriting "p:present" to "p:kiosk". 在PPTX文件中,我可以将其像zip文件一样提取并重写presProps.xml,其中包含诸如“ p:showPr useTimings =” 0“ p:present”之类的属性,并且可以通过重写“ p:present”来更改模式。改为“ p:kiosk”。 And I have just figured out that I can use apache-poi OPCPackage to do that. 我刚刚发现我可以使用apache-poi OPCPackage来做到这一点。 (eg How do I edit the presProps.xml file with ApachePoi ) (例如, 如何使用ApachePoi编辑presProps.xml文件

However, in a PPT file, I cannot do that like above. 但是,在PPT文件中,我无法像上面那样进行操作。 Is there any way that I can change the presentation mode of a PPT file. 有什么方法可以更改PPT文件的显示模式。 Or can I use apache-poi to convert a PPT file to a PPTX file so that the solution above can work? 还是可以使用apache-poi将PPT文件转换为PPTX文件,以便上述解决方案可以正常工作?

Thx. 谢谢。

A *.ppt file is a PowerPoint file stored in binary file format. *.ppt文件是以二进制文件格式存储的PowerPoint文件。 This is what org.apache.poi.hslf is made for. 这就是org.apache.poi.hslf的用途。 Entry point is the HSLFSlideShow . 入口点是HSLFSlideShow

All the office binary formats have in common that they are streams of Record data records to describe the document. 所有Office二进制格式的共同点是它们是Record数据记录流以描述文档。 For PowerPoint the specification is here: [MS-PPT]: PowerPoint (.ppt) Binary File Format . 对于PowerPoint ,规格在此处: [MS-PPT]:PowerPoint(.ppt)二进制文件格式

For your requirement there is DocumentContainer having an optional SlideShowDocInfoAtom set. 根据您的要求,有一个DocumentContainer具有可选的SlideShowDocInfoAtom集。 There F - fKioskMode (1 bit) can be set to set kiosk mode. 可以设置F - fKioskMode (1 bit)来设置信息亭模式。

The DocumentContainer can be got via HSLFSlideShow.getDocumentRecord using apache poi . 可以通过HSLFSlideShow.getDocumentRecord使用apache poi 获取 DocumentContainer But then the support from apache poi ends because the Record SlideShowDocInfoAtom is not implemented until now. 但是随后apache poi的支持终止了,因为到现在为止还没有实现Record SlideShowDocInfoAtom

But using an own class SlideShowDocInfoAtom which extends RecordAtom we can implement this. 但是,使用扩展了RecordAtom的自己的SlideShowDocInfoAtom类,我们可以实现这一点。

Example: 例:

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; }
 }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM