pptx-rs2 0.5.0

Rust 版本的 PowerPoint .pptx 读写库, 对标 python-pptx
Documentation

pptx-rs

Rust 实现的 PowerPoint .pptx / .ppt 读写库,对标 python-pptx

当前状态:0.4.0 —— MVP + 文件加密 + 图表 / SmartArt / 3D 效果 + 多母版 round-trip 保真。可创建 / 打开 / 保存 .pptx;支持幻灯片增删、文本框、段落、Run(带字体 / 字号 / 粗体 / 颜色 / 下划线)、图片插入、表格 / 连接器等基础形状;支持母版 / 版式 / 主题读写与高阶编辑支持 8 种图表类型(Column / Bar / Line / Pie / Scatter / Area / Radar / Bubble,含 Excel 嵌入 + 数据标签 + 次坐标轴 + 系列样式 + 组合图 + 读路径);支持 SmartArt(创建 + round-trip + 文本节点编辑);支持 3D 效果(旋转 / 挤出 / 斜面 / 材质);支持 OOXML Agile Encryption 文件加密(AES-256-CBC + SHA512,WPS/PowerPoint 兼容);支持水印注入。支持 .ppt(PowerPoint 97-2003 二进制格式)文件的 RC4 CryptoAPI 加密和水印注入

已知限制:打开已有 .pptx 再保存时,多母版/版式/主题场景已完整保真(from_opc 解析存储 + to_opc_package 循环透传);notesMaster 已支持写路径(读写 round-trip 保真)。

路线图

  • OPC 包容器:zip 读写、[Content_Types].xml、Part 关系链
  • Presentation / Slide / SlideLayout / SlideMaster XML 模型
  • 形状树:AutoShape、Picture、Group、Connector
  • TextFrame / Paragraph / Run / 字体/颜色
  • 常用 DrawingML 几何(<a:prstGeom> preset shapes)
  • 表格
  • 水印(向 spTree 注入半透明文本框)
  • 文件加密(OOXML Agile Encryption:AES-256-CBC + SHA512)
  • 水印+加密一步到位
  • .ppt 文件加密(RC4 CryptoAPI,MS-OFFCRYPTO 规范)
  • .ppt 文件水印注入(Escher OfficeArt SpContainer)
  • .ppt 水印+加密合并
  • 母版 / 版式 / 主题(读写 + 高阶编辑 API;round-trip 保真仍有限制,见"已知限制")
  • Chart(8 种类型:Column / Bar / Line / Pie / Scatter / Area / Radar / Bubble + Excel 嵌入 + 数据标签 / 次坐标轴 + 系列样式 + 组合图 + 读路径)
  • SmartArt(创建 + round-trip + 文本节点编辑)
  • 3D 效果(旋转 / 挤出 / 斜面 / 材质 / backdrop 背景元素)
  • 音视频嵌入add_video / add_audio + 海报帧)
  • OLE 对象嵌入add_ole_object
  • [~] 完整 round-trip 保真(多母版/版式/主题已支持;notesMaster 读写已支持)
  • 跨版本大文件兼容性测试(PowerPoint / WPS / Keynote)

安装

cargo add pptx-rs2

注意:crates.io 上的 crate 名为 pptx-rs2(原名 pptx-rs 已被他人占坑), 但代码中导入名为 pptx_rs(通过 [lib] name = "pptx_rs" 解耦)。使用时 use pptx_rs::...

或在 Cargo.toml 中手动添加:

[dependencies]

pptx-rs2 = "0.4"

快速开始

use pptx_rs::{Presentation, Pt, RGBColor};

fn main() -> pptx_rs::Result<()> {
    // 1) 全新创建
    let mut prs = Presentation::new()?;
    let counter = prs.id_counter();
    let slide = prs.slides_mut().add_slide(counter)?;
    slide.shapes_mut().add_textbox(
        pptx_rs::Inches(1.0), pptx_rs::Inches(1.0),
        pptx_rs::Inches(8.0), pptx_rs::Inches(1.0),
    )?
    .text_frame_mut()
    .set_text("Hello, rust-pptx!")
    .paragraphs_mut()
    .first_mut()
    .unwrap()
    .runs_mut()
    .first_mut()
    .unwrap()
    .font_mut()
    .set_size(Pt(40.0))
    .set_bold(true)
    .set_color(RGBColor(0x1F, 0x4E, 0x79));

    prs.save("hello.pptx")?;

    // 2) 打开已存在
    let prs = Presentation::open("hello.pptx")?;
    for (i, slide) in prs.slides().iter().enumerate() {
        println!("slide #{} has {} shape(s)", i, slide.shapes().len());
    }
    Ok(())
}

.ppt 97-2003 格式支持(库 API)

.ppt(PowerPoint 97-2003 二进制格式)与 .pptx(ZIP+XML)是完全不同的两种格式。 本库通过 pptx_rs::ppt97 模块提供 .ppt 文件的水印注入RC4 CryptoAPI 加密能力, 填补 python-pptx 不支持 .ppt 二进制格式的空白。

模块组织

src/ppt97/
├── mod.rs          # 模块入口 + 公共 API
├── record.rs       # PPT record 树解析(MS-PPT 规范)
├── ole.rs          # OLE2/CFB 容器操作(基于 cfb crate)
├── watermark.rs    # 水印注入(Escher OfficeArt SpContainer)
└── crypto.rs       # RC4 CryptoAPI 加密(MS-OFFCRYPTO 规范)

公共 API

API 功能
pptx_rs::ppt97::add_watermark(path, &config) 为 .ppt 注入水印(不可编辑背景层)
pptx_rs::ppt97::encrypt(path, password) 为 .ppt 设置 RC4 CryptoAPI 加密
pptx_rs::ppt97::add_watermark_and_encrypt(path, &config, password) 同时注入水印和加密(先水印后加密)
pptx_rs::ppt97::WatermarkConfig 水印配置(文本、字号、颜色、旋转角度)

库 API 示例

use pptx_rs::ppt97::{add_watermark, encrypt, add_watermark_and_encrypt, WatermarkConfig};
use std::path::Path;

fn main() -> pptx_rs::Result<()> {
    let input = Path::new("input.ppt");
    let config = WatermarkConfig {
        text: "机密".to_string(),
        ..Default::default()
    };

    // 1) 仅加水印
    let watermarked = add_watermark(input, &config)?;
    std::fs::write("watermarked.ppt", &watermarked)?;

    // 2) 仅加密
    let encrypted = encrypt(input, "my-password")?;
    std::fs::write("encrypted.ppt", &encrypted)?;

    // 3) 水印 + 加密(推荐用法)
    let both = add_watermark_and_encrypt(input, &config, "my-password")?;
    std::fs::write("both.ppt", &both)?;

    Ok(())
}

水印特性

  • 注入到 MainMaster 的 PPDrawing(覆盖所有幻灯片,不只是单张)
  • 作为 SpgrContainer 中"组形状本身"之后的第一个子形状(z-order 最低)
  • FOPT 保护位 0x01C2 锁定,普通视图下不可选中/不可编辑
  • 全屏覆盖(ClientAnchor 0,0 → 5760,4320)
  • 默认中灰色、可配置旋转角度、可配置文本/字号/颜色

加密特性

  • RC4 CryptoAPI 加密(MS-OFFCRYPTO 规范 2.3.5)
  • 密钥派生:H₀=SHA1(salt+password_utf16le),Hfinal=SHA1(H₀+LE32(block))
  • 每个 persist 对象独立加密(block=persistId,分段加密)
  • 不加密:UserEditAtom、PersistDirectoryAtom、Pictures stream(WPS 兼容)
  • 加密标记:CurrentUserAtom.headerToken=0xF3D1C4DF,UserEditAtom.recLen=28→32
  • 默认密码:pptx-rs-secret(可在调用时自定义)

文件加密

.pptx 文件加密(OOXML Agile Encryption)

使用 OOXML Agile Encryption(MS-OFFCRYPTO 规范),输出可被 WPS / PowerPoint / msoffcrypto-python 正确解密:

# 仅加密

cargo run --example protect_pptx


# 水印+加密

cargo run --example watermark_and_protect

加密参数:

  • 算法:AES-256-CBC + SHA512
  • 密钥派生:PBKDF2(100000 次迭代)
  • 容器:OLE2/CFB(DataSpaces + EncryptionInfo + EncryptedPackage)
  • 默认密码:pptx-rs-secret

.ppt 文件加密(RC4 CryptoAPI)

支持 PowerPoint 97-2003 二进制格式(.ppt)的 RC4 CryptoAPI 加密,输出可被 msoffcrypto-python 正确解密。 推荐使用 pptx_rs::ppt97 库 API,examples 仅作为命令行封装:

# 仅加密(库 API: pptx_rs::ppt97::encrypt)

cargo run --example protect_ppt


# 水印+加密(库 API: pptx_rs::ppt97::add_watermark_and_encrypt)

cargo run --example watermark_and_protect_ppt

加密参数:

  • 算法:RC4 + SHA1 密钥派生(MS-OFFCRYPTO 规范)
  • 密钥位数:128 bit
  • 容器:OLE2/CFB(PowerPoint Document + Current User stream)
  • 加密结构:CryptSession10Container + PersistDirectoryAtom 更新
  • 每个 persist 对象独立加密(block=persistId,分段加密)
  • 默认密码:pptx-rs-secret

水印

.pptx 水印

cargo run --example watermark_pptx

水印特性:

  • 浅灰色半透明 40pt 粗体文字 "pptx-rs WATERMARK"
  • 旋转 -45°,位于幻灯片中央
  • 不重新声明 xmlns(WPS 兼容)

.ppt 水印

# 库 API: pptx_rs::ppt97::add_watermark

cargo run --example watermark_ppt

水印特性:

  • 在每个 MainMaster 的 PPDrawing 中注入水印 SpContainer(不可编辑背景层)
  • Escher OfficeArt 二进制结构(FSP / FOPT / ClientAnchor / ClientTextbox)
  • TextCharsAtom(UTF-16LE)水印文本 "pptx-rs 水印"
  • 加水印后正确更新所有 persist 对象的 offset
  • 作为 SpgrContainer 中"组形状本身"之后的第一个子形状(z-order 最低)
  • FOPT 保护位 0x01C2 锁定,普通视图下不可选中/不可编辑

与 python-pptx 的对应关系

python-pptx pptx-rs
Presentation() Presentation::new()
Presentation(path) Presentation::open(path)
prs.save(path) prs.save(path)
prs.slides prs.slides() / prs.slides_mut()
prs.slide_width / slide_height Emu 类型字段
prs.slide_masters / slide_master prs.slide_masters() / prs.slide_master(idx)
prs.slide_layouts prs.slide_layouts() / prs.slide_layout(idx)
slide.shapes slide.shapes() / slide.shapes_mut()
shapes.add_textbox(l, t, w, h) shapes_mut().add_textbox(l, t, w, h)
shapes.add_picture(path, l, t, w, h) shapes_mut().add_picture(path, l, t, w, h)
shapes.add_chart(chart_type, data, x, y, cx, cy) shapes_mut().add_chart(chart_type, data, l, t, w, h)
shapes.add_ole_object(...) shapes_mut().add_ole_object(path, prog_id, name, l, t, w, h)
shape.text_frame.text = "…" shape.text_frame_mut().set_text("…")
run.font.size = Pt(24) run.font_mut().set_size(Pt(24.0))
run.font.bold = True run.font_mut().set_bold(true)
chart.plots[0].has_data_labels chart_shape.set_data_labels(...) / series_data_labels(...)

注:python-pptx 当前不支持 SmartArt 创建 / 编辑,本库通过 shapes_mut().add_smartart(...) 提供此能力。

命名

类型 说明
Emu(i64) English Metric Unit,1 inch = 914400 EMU
Pt(f64) 磅,1 pt = 12700 EMU
Inches(f64) 英寸
RGBColor(u8, u8, u8) sRGB 颜色

示例

示例 说明
hello_pptx 创建包含文本框的演示文稿
watermark_pptx 为现有 .pptx 添加水印
protect_pptx 为现有 .pptx 设置文件加密
watermark_and_protect 同时添加水印和加密(.pptx)
protect_ppt 为现有 .ppt 设置 RC4 CryptoAPI 加密
watermark_ppt 为现有 .ppt 添加水印
watermark_and_protect_ppt 同时添加水印和加密(.ppt)
text_format_demo 文本格式化演示
shapes_demo 各种形状演示
connector_demo 连接器演示
chart_demo 图表演示(柱 / 线 / 饼 / 散点 / 面积 5 种)
media_demo 音视频嵌入演示(add_video / add_audio
ole_demo OLE 对象嵌入演示(add_ole_object
test_pictures_encryption 图片加密验证
test_copy_ppt .ppt 复制验证

文档

许可

MIT