Delete a slide from a presentation

Deleting a slide is a coordinated edit to ppt/presentation.xml, the presentation relationships, and possibly related notes, comments, media, and custom show data. Removing only the slide XML file leaves dangling relationships or slide ids.

The upstream workflow first counts slides, then deletes a slide by zero-based index. Counting can be read-only; deletion must open the package for editing.

What must change

A slide is listed in <p:sldIdLst/>:

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

The relationship id points to a slide part:

<Relationship
  Id="rId2"
  Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"
  Target="slides/slide2.xml"/>

A safe deletion removes the slide id entry and the relationship, then checks whether related slide resources are still referenced.

Custom shows need special handling. A custom show stores its own slide list by relationship ID, so every reference to the deleted slide relationship must be removed from every custom show before the slide part is deleted.

More complex presentations can have additional references, such as outline view settings or extension data. Treat slide deletion as package graph cleanup, not just an XML list edit.

Rust workflow

Remove the slide id entry and delete the related slide part from the presentation part:

#![allow(unused)]
fn main() {
pub fn delete_slide(
  path: &Path,
  slide_index: usize,
) -> 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 slides: Vec<_> = presentation_part.slide_parts(&document).collect();
  let Some(slide_part) = slides.get(slide_index).cloned() else {
    return Err("slide index out of range".into());
  };
  let presentation_xml = presentation_part
    .data_as_str(&document)?
    .unwrap_or_default();
  let updated_xml = remove_slide_id(presentation_xml, slide_index)?;

  presentation_part.delete_part(&mut document, slide_part)?;
  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 presentations that use custom shows, notes, comments, or slide-specific media, delete or rewrite those related resources before saving. The example above covers the primary presentation slide list and slide part relationship.