Как изменить режим презентации ppt, используя apache-poi или другую 3-ю библиотеку? - PullRequest
0 голосов
/ 22 декабря 2018

Я работаю над проектом, который должен отображать файл PPT в режиме презентации "киоск".В файле PPTX я могу извлечь его как zip-файл и переписать файл presProps.xml, который содержит такие свойства, как "p: showPr useTimings =" 0 "p: present", и я могу изменить режим, переписав "p: present"в "p: киоск".И я только что понял, что я могу использовать apache-poi OPCPackage для этого.(например, Как мне отредактировать файл presProps.xml с помощью ApachePoi )

Однако в файле PPT я не могу сделать это, как описано выше.Есть ли способ, которым я могу изменить режим представления файла PPT.Или я могу использовать apache-poi для преобразования PPT-файла в PPTX-файл, чтобы вышеприведенное решение могло работать?

Thx.

1 Ответ

0 голосов
/ 23 декабря 2018

A *.ppt - это файл PowerPoint, сохраненный в двоичном формате.Для этого и создана org.apache.poi.hslf .Точкой входа является HSLFSlideShow .

Все офисные двоичные форматы имеют общее то, что они представляют собой потоки записей данных Record для описания документа.Для PowerPoint спецификация здесь: [MS-PPT]: формат двоичных файлов PowerPoint (.ppt) .

Для ваших требований есть DocumentContainer с дополнительным набором SlideShowDocInfoAtom .Там F - fKioskMode (1 bit) можно установить для установки режима киоска.

DocumentContainer можно получить через HSLFSlideShow.getDocumentRecord , используя apache poi.Но тогда поддержка из apache poi заканчивается, потому что Record 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; }
 }

}
...