Replace the header in a word processing document

Headers are stored in separate header parts and referenced from section properties. Replacing a header can mean editing the existing header part or creating a new part and updating the section reference.

Each headerReference points to a header part by relationship id. The relationship must be internal and use the header relationship type. The reference also has a type attribute that selects which header slot it fills.

Header reference markup

<w:sectPr>
  <w:headerReference r:id="rId3" w:type="first"/>
  <w:headerReference r:id="rId5" w:type="default"/>
  <w:headerReference r:id="rId2" w:type="even"/>
</w:sectPr>

Sections can define first-page, even-page, and default headers. Missing references are inherited or substituted according to section settings such as titlePg and document settings such as even/odd headers.

Rust workflow

Use the main document part to locate or create a header part, write the header XML, and update the default section reference:

#![allow(unused)]
fn main() {
pub fn replace_header(
  path: &Path,
  header_text: &str,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
  let mut document = WordprocessingDocument::new_from_file_with_settings(path, lazy_settings())?;
  let main_part = document.main_document_part()?;
  let header_part = if let Some(part) = main_part.header_parts(&document).next() {
    part
  } else {
    main_part.add_new_part_auto_id::<_, HeaderPart>(&mut document)?
  };
  let relationship_id = main_part
    .get_id_of_part(&document, &header_part)
    .expect("header relationship id")
    .to_string();

  header_part.set_data(&mut document, header_xml(header_text).into_bytes())?;
  let document_xml = main_part.data_as_str(&document)?.unwrap_or_default();
  let updated_xml = set_header_reference(document_xml, &relationship_id)?;

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

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

This example updates the default header slot. Apply the same relationship and section-property pattern for first-page or even-page headers by changing the w:type value and targeting the corresponding header part.

In ooxmlsdk, MainDocumentPart::header_parts(&document) traverses header parts. Generated schema types include Header, HeaderReference, and SectionProperties.