Insert a new slide into a presentation

Inserting a slide requires creating a slide part, adding a presentation relationship, inserting a <p:sldId/> entry at the desired position, and linking the slide to a layout. A valid slide usually depends on an existing slide master and slide layout.

Relationship model

The presentation part orders slides through <p:sldIdLst/>:

<p:sldIdLst>
  <p:sldId id="256" r:id="rId1"/>
  <p:sldId id="257" r:id="rId2"/>
</p:sldIdLst>

The id value is a presentation slide id. The r:id value resolves to a slide part relationship.

Insert workflow

The upstream sample takes a file path, a zero-based insertion index, and a title string. It then:

  1. Creates a new p:sld root and common slide data.
  2. Adds a title shape and sets its text.
  3. Adds a body shape and sets its text or placeholder properties.
  4. Creates a new slide part.
  5. Inserts a new p:sldId entry at the requested index.
  6. Assigns the new slide root to the new slide part.

In a complete package, the new slide should also have a slide layout relationship. Copying the layout relationship from a nearby slide is often safer than inventing one from scratch.

Rust workflow

Create a slide part, optionally reuse an existing layout relationship, and insert a new slide id at the requested position:

#![allow(unused)]
fn main() {
pub fn insert_new_slide(
  path: &Path,
  insertion_index: usize,
  title: &str,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
  let mut document = PresentationDocument::new_from_file_with_settings(path, lazy_settings())?;
  let presentation_part = document.presentation_part()?;
  let slide_count = presentation_part.slide_parts(&document).count();
  if insertion_index > slide_count {
    return Err("insertion index out of range".into());
  }

  let layout_part = presentation_part
    .slide_parts(&document)
    .find_map(|slide| slide.slide_layout_part(&document));
  let slide_part = presentation_part.add_new_part_auto_id::<_, SlidePart>(&mut document)?;
  if let Some(layout_part) = layout_part {
    slide_part.create_relationship_to_part(&mut document, layout_part)?;
  }
  slide_part.set_data(&mut document, slide_xml(title).into_bytes())?;
  let relationship_id = presentation_part
    .get_id_of_part(&document, &slide_part)
    .expect("slide relationship id")
    .to_string();
  let presentation_xml = presentation_part
    .data_as_str(&document)?
    .unwrap_or_default();
  let updated_xml = insert_slide_id(presentation_xml, insertion_index, &relationship_id)?;

  presentation_part.set_data(&mut document, updated_xml.into_bytes())?;

  let mut buffer = Cursor::new(Vec::new());
  document.save(&mut buffer)?;
  Ok(buffer.into_inner())
}
}

For rich layouts, copy an existing slide and adjust its content before attempting a fully from-scratch slide. The example above creates a simple title slide and keeps the package graph consistent with the presentation slide list.