Working with notes slides

A notes slide stores speaker notes and related presentation content for a single slide. It is a separate part related from the slide part.

Notes slide structure

The root element is <p:notes/>. It can contain common slide data, a color map override, and extension data. The actual note text is usually stored in text bodies under shapes.

<p:notes
  xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"
  xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
  <p:cSld>
    <p:spTree>
      <p:nvGrpSpPr>
        <p:cNvPr id="1" name=""/>
        <p:cNvGrpSpPr/>
        <p:nvPr/>
      </p:nvGrpSpPr>
      <p:grpSpPr/>
      <p:sp>
        <p:nvSpPr>
          <p:cNvPr id="2" name="Notes placeholder 2"/>
          <p:cNvSpPr/>
          <p:nvPr/>
        </p:nvSpPr>
        <p:spPr/>
        <p:txBody>
          <a:bodyPr/>
          <a:lstStyle/>
          <a:p><a:r><a:t>Speaker note</a:t></a:r></a:p>
        </p:txBody>
      </p:sp>
    </p:spTree>
  </p:cSld>
</p:notes>

Common elements:

PresentationML elementPurpose
<p:cSld/>Common notes slide data
<p:clrMapOvr/>Color map override
<p:extLst/>Extension data

Important notes slide attributes include:

AttributeMeaning
showMasterPhAnimWhether to display animations on master placeholders
showMasterSpWhether to show shapes from the master

p:clrMapOvr can use a:masterClrMapping to inherit the master color scheme, or a:overrideClrMapping to define a notes-specific mapping.

Rust workflow

Start from the slide part and follow its notes slide relationship if present. The general traversal pattern is the same as reading slide text:

#![allow(unused)]
fn main() {
pub fn get_slide_text(
  path: &Path,
  slide_index: usize,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
  let document = PresentationDocument::new_from_file_with_settings(path, lazy_settings())?;
  let presentation_part = document.presentation_part()?;
  let Some(slide_part) = presentation_part.slide_parts(&document).nth(slide_index) else {
    return Ok(Vec::new());
  };
  let xml = slide_part.data_as_str(&document)?.unwrap_or_default();

  Ok(extract_drawing_text(xml))
}
}

ooxmlsdk provides the package and typed part graph. A writer for notes slides needs to update the slide relationship, notes part XML, optional notes master references, and content type declarations together; this chapter keeps that as future tested work.

When adding notes to a deck that lacks notes infrastructure, also account for the notes master part and its theme relationship. The upstream sample creates missing notes slide, notes master, and theme parts together.