簡體   English   中英

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

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

我一直在從事一個需要以“信息亭”演示模式顯示PPT文件的項目。 在PPTX文件中,我可以將其像zip文件一樣提取並重寫presProps.xml,其中包含諸如“ p:showPr useTimings =” 0“ p:present”之類的屬性,並且可以通過重寫“ p:present”來更改模式。改為“ p:kiosk”。 我剛剛發現我可以使用apache-poi OPCPackage來做到這一點。 (例如, 如何使用ApachePoi編輯presProps.xml文件

但是,在PPT文件中,我無法像上面那樣進行操作。 有什么方法可以更改PPT文件的顯示模式。 還是可以使用apache-poi將PPT文件轉換為PPTX文件,以便上述解決方案可以正常工作?

謝謝。

*.ppt文件是以二進制文件格式存儲的PowerPoint文件。 這就是org.apache.poi.hslf的用途。 入口點是HSLFSlideShow

所有Office二進制格式的共同點是它們是Record數據記錄流以描述文檔。 對於PowerPoint ,規格在此處: [MS-PPT]:PowerPoint(.ppt)二進制文件格式

根據您的要求,有一個DocumentContainer具有可選的SlideShowDocInfoAtom集。 可以設置F - fKioskMode (1 bit)來設置信息亭模式。

可以通過HSLFSlideShow.getDocumentRecord使用apache poi 獲取 DocumentContainer 但是隨后apache poi的支持終止了,因為到現在為止還沒有實現Record SlideShowDocInfoAtom

但是,使用擴展了RecordAtom的自己的SlideShowDocInfoAtom類,我們可以實現這一點。

例:

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