如何重命名幻灯片母版

时间:2019-01-19 09:45:12

标签: apache-poi powerpoint master

我想用$ googlesamples-assistant-hotword --project-id xxxxx --device-model-id xxxxx device_model_id: xxxxx device_id: BE5AC9Dxxxxxxxxxxxxxxxxxxxxxxx Segmentation fault 重命名PowerPoint幻灯片母版。在apache poi GUI中,我们执行PowerPoint-View-然后右键单击左侧最上方的幻灯片,然后从上下文菜单中选择Slide Master

enter image description here

1 个答案:

答案 0 :(得分:1)

PowerPoint演示文稿中,母版被命名为主题。我们可以使用XMLSlideShow.getSlideMasters来获得所有大师。 XSLFSlideMaster 扩展XSLFSheet。因此,我们可以使用XSLFSheet.getTheme获取每个母版的主题。一旦有了XSLFTheme,名称的获取器和设置器便会出现。

示例:

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.poi.xslf.usermodel.*;

public class XSLFRenameMasterTheme {

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

  XMLSlideShow slideshow = new XMLSlideShow(new FileInputStream("Presentation.pptx"));

  for (XSLFSlideMaster master : slideshow.getSlideMasters()) {
   XSLFTheme theme = master.getTheme();
   String name = theme.getName();
System.out.println(name);
   theme.setName(name + " renamed");
System.out.println(theme.getName());
  }

  FileOutputStream out = new FileOutputStream("PresentationRenamedMaster.pptx");
  slideshow.write(out);
  out.close();
  slideshow.close();
 }
}

对于HSLFSlideShow,似乎无法访问支持的主名称。可以获取HSLFSlideMaster,但不能获取其名称。

因此,如果仍然需要这样做,则必须了解二进制*.ppt文件系统的内部。 [MS-PPT]: PowerPoint (.ppt) Binary File Format中对此进行了说明。工作表名称位于SlideNameAtom中。有了有关内部知识的知识,就可以为此类记录创建一个类。这样可以提供获取和设置名称的方法。

示例:

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

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

import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;

public class HSLFRenameMaster {

 // method for get SlideNameAtom out of the master
 private static SlideNameAtom getSlideNameAtom(HSLFSlideMaster master) throws Exception {
  SlideNameAtom slideNameAtomRecord = null;
  Record record = master.getSheetContainer().findFirstOfType(0x0FBA);
  if (record != null) { // SlideNameAtom exists
   // get present data
   ByteArrayOutputStream out = new ByteArrayOutputStream();
   record.writeOut(out);
   out.flush();
   byte[] data = out.toByteArray();
   out.close();
   // create new SlideNameAtom from data
   slideNameAtomRecord = new SlideNameAtom(data);
   // replace old record with new SlideNameAtom
   master.getSheetContainer().addChildBefore(
    slideNameAtomRecord,
    record
   );
   master.getSheetContainer().removeChild(record);
  } 
  return slideNameAtomRecord;
 }


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

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

  for (HSLFSlideMaster master : slideshow.getSlideMasters()) {
   SlideNameAtom slideNameAtomRecord = getSlideNameAtom(master);
   if (slideNameAtomRecord != null) {
    String name = slideNameAtomRecord.getName();
System.out.println(name);
    slideNameAtomRecord.setName(name + " renamed");
System.out.println(slideNameAtomRecord.getName());
   }
  }

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

 //class SlideNameAtom 
 //having methods for manipulating the [SlideNameAtom](https://msdn.microsoft.com/en-us/library/dd906297(v=office.12).aspx)
 private static class SlideNameAtom extends RecordAtom {

  private byte[] data;
  private String name;

  public SlideNameAtom() {
   this.name = "Office";
   setName(name);
  }

  public SlideNameAtom(byte[] data) {
   this.data = data;
   this.name = getName();
  }

  public void setName(String name) {
   this.name = name;
   int length = 8;
   length += StringUtil.getToUnicodeLE(name).length;
   this.data = new byte[length];
   data[0] = (byte)0x20; data[1] = (byte)0x00; 
   data[2] = (byte)0xBA; data[3] = (byte)0x0F; //MUST be 0x0fba = RT_CString (little endian)
   LittleEndian.putInt(data, 4, StringUtil.getToUnicodeLE(name).length);
   StringUtil.putUnicodeLE(name, data, 8);
  }

  public String getName() {
   return StringUtil.getFromUnicodeLE(this.data, 8, (this.data.length-8)/2);
  }

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

  @Override
  public long getRecordType() { return 0x0FBA; }
 }

}

问题是重命名母版是否值得这样做。