Skip to main content

Presentation

Struct Presentation 

Source
pub struct Presentation { /* private fields */ }
Expand description

演示文稿(内存模型)。

§字段语义

  • slides / slide_layouts / slide_masters:三类“主-版-页“集合;
  • width / height:画布尺寸,序列化为 <p:sldSz cx="..." cy="..."/>
  • id_counter:共享 ID 计数器(每张 slide / 每个 shape 都会 next_shape_id);
  • 媒体(图片等 blob)按 slide 存储——参见 Slide::register_media。 保存时由 to_opc_package 遍历 self.slides 聚合写入 zip;同一 partname 只写一次。

Implementations§

Source§

impl Presentation

Source

pub fn new() -> Result<Self>

新建一个完全空白的演示文稿。

内部会做两件事:

  1. id_counter 初始化为 2(保留 1 给“隐藏占位“用途,与 Office 一致);
  2. 调用 Presentation::ensure_default_master_and_layout 创建 1 个 默认母版 + 1 个空白版式,保证保存出的 .pptx 在 PowerPoint 中能正常打开。
§错误

当前实现不会失败;保留 Result 是为后续扩展(例如从模板加载 master)留口。

Source

pub fn open(path: impl AsRef<Path>) -> Result<Self>

打开一个已存在的 .pptx 文件并解析为内存模型。

等价于 Presentation::load,提供“短名 + 详细名“两个入口。

§错误
  • crate::Error::Io:文件不存在或权限不足;
  • crate::Error::Zip:zip 损坏;
  • crate::Error::Xml:内部 XML 无法解析(注意:当前 read 路径尚未完整实现, 实际只解析 [Content_Types].xml,其它 part 暂未还原到 oxml 模型)。
Source

pub fn load(path: &Path) -> Result<Self>

加载 .pptx 的详细入口(与 Presentation::open 等价)。

Source

pub fn load_bytes(bytes: &[u8]) -> Result<Self>

从内存中的 zip 字节流加载。

Presentation::load 的区别:本方法触发磁盘 IO,可用于:

  • Web 服务接收 multipart/form-data 上传后的字节流;
  • 单元测试中 fixture 来自 include_bytes! 的场景;
  • 通过 std::io::Cursor 包装任意 Read 来源。
§错误
Source

pub fn slides(&self) -> &Slides

不可变幻灯片集合。

Source

pub fn slides_mut(&mut self) -> &mut Slides

可变幻灯片集合。

Source

pub fn id_counter(&self) -> Rc<Cell<u32>>

取出共享的 id_counter 克隆。

Slides::add_slide 接受这个计数器,从而保证跨 slide 的 shape id 不冲突。

Source

pub fn slide_layouts(&self) -> &SlideLayouts

不可变版式集合。

Source

pub fn slide_layouts_mut(&mut self) -> &mut SlideLayouts

可变版式集合。

Source

pub fn layout_for_slide(&self, slide_idx: usize) -> Option<SlideLayoutRef>

按 slide 索引取该 slide 所引用的版式(TODO-007)。

对标 python-pptx slide.slide_layout。本方法通过匹配 slide.layout_rid()SlideLayoutRef.rid() 查找。

§参数
  • slide_idx:slide 在 slides 集合中的索引。
§返回
  • Some(SlideLayoutRef):找到匹配的版式(克隆,因 SlideLayoutRefClone);
  • None:索引越界,或未找到 rid 匹配的版式。
§示例
use pptx_rs::Presentation;
let mut p = Presentation::new().unwrap();
let counter = p.id_counter();
let _ = p.slides_mut().add_slide(counter).unwrap();
// 获取第 0 张 slide 所引用的版式
if let Some(layout) = p.layout_for_slide(0) {
    println!("版式名: {}", layout.name());
}
Source

pub fn slides_using_layout(&self, layout_rid: &str) -> Vec<usize>

获取使用指定版式的所有 slide 索引(TODO-008)。

对标 python-pptx SlideLayout.used_by_slides

§参数
  • layout_rid:版式的关系 id(SlideLayoutRef.rid())。
§返回

所有 layout_rid() 等于 layout_rid 的 slide 索引列表(升序)。

Source

pub fn slide_masters(&self) -> &SlideMasters

不可变母版集合。

Source

pub fn slide_masters_mut(&mut self) -> &mut SlideMasters

可变母版集合。

Source

pub fn slide_width(&self) -> Emu

当前画布宽度(EMU)。

Source

pub fn slide_height(&self) -> Emu

当前画布高度(EMU)。

Source

pub fn set_slide_size(&mut self, width: Emu, height: Emu)

显式设置画布尺寸。

注意此方法触发任何 Slide 内部 shape 的重新布局;shape 仍按各自的 EMU 坐标保存,调用方需自行决定是否缩放。

Source

pub fn core_properties(&self) -> &CoreProperties

取文档核心属性(不可变引用)。

对标 pypdf PdfReader.metadata / python-pptx Presentation.core_properties

Source

pub fn core_properties_mut(&mut self) -> &mut CoreProperties

取文档核心属性(可变引用)。

对标 pypdf PdfWriter.add_metadata(infos)。 修改后会在 save / to_bytes 时序列化到 docProps/core.xmldocProps/app.xml

Source

pub fn custom_properties(&self) -> &CustomProperties

取自定义文档属性(不可变引用)。

对标 python-pptx Presentation.custom_properties(v1.0+)。

Source

pub fn custom_properties_mut(&mut self) -> &mut CustomProperties

取自定义文档属性(可变引用)。

修改后会在 save / to_bytes 时序列化到 docProps/custom.xml

§示例
use pptx_rs::Presentation;
use pptx_rs::presentation::CustomPropertyValue;

let mut p = Presentation::new().unwrap();
p.custom_properties_mut().set("Project", CustomPropertyValue::Text("Demo".to_string()));
p.custom_properties_mut().set("Version", CustomPropertyValue::Int(42));
Source

pub fn comment_authors(&self) -> &CommentAuthorList

取评论作者列表(不可变引用)。

评论作者在 save / to_bytes 时序列化到 /ppt/commentAuthors.xml

Source

pub fn comment_authors_mut(&mut self) -> &mut CommentAuthorList

取评论作者列表(可变引用)。

修改后会在 save / to_bytes 时序列化到 /ppt/commentAuthors.xml

§示例
use pptx_rs::Presentation;

let mut p = Presentation::new().unwrap();
let author_id = p.comment_authors_mut().get_or_insert_id("张三", "ZS");
Source

pub fn sections(&self) -> &SectionList

取章节分组列表(不可变引用,TODO-039)。

章节分组对应 PowerPoint 大纲视图中的“节“功能,在 presentation.xml<p:extLst> 内以 <p14:sectionLst> 扩展元素持久化。

§与 python-pptx 的对应

python-pptx 截至 v1.0 仍未提供 section API,本方法是 pptx-rs 的扩展。

Source

pub fn sections_mut(&mut self) -> &mut SectionList

取章节分组列表(可变引用,TODO-039)。

修改后会在 save / to_bytes 时序列化到 presentation.xml<p:extLst><p:ext uri="{521415D9-36F7-43E2-AB2F-B90AF26B5E64}"> 内的 <p14:sectionLst>

§示例
use pptx_rs::Presentation;
use pptx_rs::oxml::section::Section;

let mut p = Presentation::new().unwrap();
// 假设已添加 2 张 slide,它们的 sld_id 分别为 256 / 257
let mut s1 = Section::new("引言");
s1.push(256);
s1.push(257);
p.sections_mut().push(s1);
Source

pub fn notes_masters(&self) -> &NotesMasters

取备注母版集合(不可变引用,TODO-045)。

备注母版是所有备注页的“模板“——定义了备注页的默认占位符与文本样式。 一个演示文稿通常只有 0 或 1 个备注母版。

§与 python-pptx 的对应
  • pptx.Presentation.notes_master ←→ presentation.notes_masters().first()
  • python-pptx 仅暴露单个 notes_master 属性,本库用集合表达以兼容多母版场景。
§示例
use pptx_rs::Presentation;

let p = Presentation::new().unwrap();
// 空白文档无备注母版
assert!(p.notes_masters().is_empty());
Source

pub fn notes_masters_mut(&mut self) -> &mut NotesMasters

取备注母版集合(可变引用,TODO-045)。

主要用于在内存中修改已解析出的备注母版形状(写路径暂未实现持久化)。

Source

pub fn notes_master(&self) -> Option<&NotesMasterRef>

便捷方法:取第一个备注母版(python-pptx presentation.notes_master 风格)。

None 表示该演示文稿无备注母版。

Source

pub fn set_metadata( &mut self, title: Option<&str>, creator: Option<&str>, subject: Option<&str>, keywords: Option<&str>, )

一次性设置多个核心属性(便捷方法)。

对标 pypdf PdfWriter.add_metadata(infos) 的“批量设置“语义。 传入 None 的字段不会覆盖已有值。

§示例
use pptx_rs::Presentation;
let mut p = Presentation::new().unwrap();
p.set_metadata(
    Some("My Presentation"),  // title
    Some("Author Name"),      // creator
    None,                     // subject (keep existing)
    None,                     // keywords
);
Source

pub fn num_slides(&self) -> usize

幻灯片总数。

对标 pypdf PdfReader.num_pages / python-pptx len(prs.slides)

Source

pub fn add_watermark( &mut self, text: &str, font_size_pt: Option<f64>, color: Option<RGBColor>, rotation_deg: Option<i32>, alpha: Option<i32>, font_name: Option<&str>, ) -> Result<()>

给所有 slide 添加文本水印

对标 pypdf PageObject.merge_page(watermark_page) 的水印注入模式。

§实现原理

在每张 slide 上添加一个旋转 + 半透明的文本框(p:sp + cNvSpPr txBox="1"), 位于 slide 中心,字体大小可配置。文本框的 z-order 被推到最顶层 (即最后添加的形状),确保水印覆盖在内容之上。

§参数
  • text:水印文本(如 “CONFIDENTIAL” / “DRAFT”);
  • font_size_pt:字体大小(磅),默认 36;
  • color:水印颜色,默认灰色 RGBColor(0xC0, 0xC0, 0xC0)
  • rotation_deg:旋转角度(度),默认 -30(逆时针 30°);
  • alpha:不透明度(0-100000),默认 30_000(30% 不透明 / 70% 透明);
  • font_name:字体名称,默认 “Calibri”。
§与 pypdf 的差异
  • pypdf 用“页面合并“(merge_page)实现水印——把水印 PDF 页叠加到目标页;
  • 本方法用“形状注入“——直接在 slide XML 中插入一个旋转文本框。 两种方式在视觉上等价,但 OOXML 不支持“页面合并“语义。
Source

pub fn add_image_watermark( &mut self, image_bytes: &[u8], ext: &str, alpha: Option<i32>, left: Option<Emu>, top: Option<Emu>, width: Option<Emu>, height: Option<Emu>, ) -> Result<()>

给所有 slide 添加图片水印

对标 pypdf PageObject.merge_page(watermark_page) 的水印注入模式。

§实现原理

在每张 slide 上添加一个半透明的图片形状(p:pic + a:alphaModFix), 位于 slide 中心,大小可配置。图片的 z-order 被推到最顶层 (即最后添加的形状),确保水印覆盖在内容之上。

§参数
  • image_bytes:图片二进制数据(PNG / JPG / BMP 等);
  • ext:图片扩展名(如 "png" / "jpg",不含前导 .);
  • alpha:不透明度(0-100000),默认 30_000(30% 不透明 / 70% 透明);
  • left:水印左上角 x 坐标(EMU),默认居中偏左 1/4 画布宽度;
  • top:水印左上角 y 坐标(EMU),默认居中偏上 1/4 画布高度;
  • width:水印宽度(EMU),默认画布宽度的一半;
  • height:水印高度(EMU),默认画布高度的一半。
§与文本水印的差异
  • 文本水印(add_watermark)用旋转文本框实现,适合“CONFIDENTIAL“等文字;
  • 图片水印用半透明图片实现,适合公司 logo / 自定义图案等场景。
§错误
Source

pub fn set_write_protection(&mut self, password: &str) -> Result<()>

设置修改密码保护(打开时可只读浏览,修改需密码)。

对标 PowerPoint “保护演示文稿 → 限制访问” 功能。

§算法

使用 SHA-512 + 随机 salt + 100 000 次迭代,符合 MS-OFFCRYPTO §2.4.2.4。 保护信息注入到 presentation.xml<p:modifyVerifier> 元素中。

§参数
  • password:修改密码(不能为空)。
§错误
Source

pub fn verify_write_protection(&self, password: &str) -> Result<bool>

验证修改密码是否匹配。

§参数
  • password:待验证的密码。
§返回
  • Ok(true):密码匹配;
  • Ok(false):密码不匹配;
  • 若未设置修改保护,返回 Ok(false)
Source

pub fn remove_write_protection(&mut self)

移除修改密码保护。

Source

pub fn is_write_protected(&self) -> bool

检查是否设置了修改密码保护。

Source

pub fn save_encrypted( &self, path: impl AsRef<Path>, password: &str, ) -> Result<()>

保存为加密的 .pptx 文件(打开文件需密码)。

对标 PowerPoint “保护演示文稿 → 用密码进行加密” 功能。 使用 ECMA-376 Agile Encryption(AES-256-CBC + SHA-512)。

§参数
  • path:输出文件路径;
  • password:加密密码。
§错误
Source

pub fn to_encrypted_bytes(&self, password: &str) -> Result<Vec<u8>>

序列化为加密的字节流(打开需密码)。

等价于“保存到内存“的加密版本,适用于网络传输等场景。

Source

pub fn open_encrypted(path: impl AsRef<Path>, password: &str) -> Result<Self>

打开加密的 .pptx 文件。

§参数
  • path:文件路径;
  • password:解密密码。
§错误
Source

pub fn load_encrypted_bytes(bytes: &[u8], password: &str) -> Result<Self>

从加密的字节流加载。

Source

pub fn is_encrypted_file(path: impl AsRef<Path>) -> Result<bool>

检查文件是否为加密的 OOXML 文档。

加密文档的特征:ZIP 中包含 EncryptionInfo 条目。

Source

pub fn is_encrypted_bytes(bytes: &[u8]) -> bool

检查字节流是否为加密的 OOXML 文档。

Source

pub fn save(&self, path: impl AsRef<Path>) -> Result<()>

保存到本地 .pptx 文件。

§错误

透传 Presentation::to_opc_packageOpcPackage::save 的一切错误。

Source

pub fn to_bytes(&self) -> Result<Vec<u8>>

把整份演示文稿序列化为 zip 字节流。

等价于“保存到内存“——适用于网络响应、自动化测试 fixture、邮件附件等场景。

Trait Implementations§

Source§

impl Debug for Presentation

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Presentation

Source§

fn default() -> Self

Default 等价于 Presentation::new

Default trait 签名无法返回 Result,因此此处使用 expect。 安全性保证:Presentation::new() 当前实现不会返回 Err(仅做 字段初始化),如果未来 new() 可能失败,应移除 Default impl 并改为关联常量或工厂方法。

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V