Replace the theme part in a word-processing document

This example replaces the WordprocessingML package's theme part with caller-provided theme XML.

A theme part contains DrawingML theme information such as color scheme, font scheme, and format scheme. In a word-processing document, the main document part can have an optional relationship to a theme part.

The same theme model is used across Office document families. A theme can affect fonts, colors, fills, backgrounds, and effects for themed objects.

Theme element structure

The root element is a:theme, represented by ooxmlsdk::schemas::a::Theme. Its themeElements child is required and carries the base color, font, and format schemes. Other children are optional:

XML elementRust typePurpose
a:themeElementsooxmlsdk::schemas::a::ThemeElementsBase theme formatting
a:objectDefaultsooxmlsdk::schemas::a::ObjectDefaultsDefault formatting for objects
a:extraClrSchemeLstooxmlsdk::schemas::a::ExtraColorSchemeListAdditional color schemes
a:custClrLstooxmlsdk::schemas::a::CustomColorListCustom colors
a:extLstooxmlsdk::schemas::a::OfficeStyleSheetExtensionListFuture extensibility

Replace the theme XML

#![allow(unused)]
fn main() {
pub fn replace_theme_part(
  path: &Path,
  theme_xml: &[u8],
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
  let settings = OpenSettings {
    open_mode: PackageOpenMode::Lazy,
    ..Default::default()
  };
  let mut document = WordprocessingDocument::new_from_file_with_settings(path, settings)?;
  let main_part = document.main_document_part()?;

  let theme_part = match main_part.theme_part(&document) {
    Some(theme_part) => theme_part,
    None => main_part.add_new_part_auto_id::<_, ThemePart>(&mut document)?,
  };

  theme_part.set_data(&mut document, theme_xml.to_vec())?;

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

The function:

  1. Opens an existing .docx.
  2. Gets the main document part.
  3. Uses the existing theme part when present.
  4. Adds a theme part when the main document part does not have one.
  5. Writes the provided XML bytes into the theme part.
  6. Saves the updated package to memory.

The theme_xml argument must be valid theme part XML. set_data writes bytes to the part; it does not prove that the XML is semantically valid for every Office version.

You can extract a valid theme XML payload from another .docx or .thmx file by treating the file as a ZIP package and locating its theme part.

Theme part relationship

The theme relationship type is:

http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme

For WordprocessingML packages, the theme part is usually stored under word/theme/theme1.xml, but callers should use the part relationship rather than hard-coding the ZIP path.