12个版本

0.2.8 2023年11月7日
0.2.7 2023年8月16日
0.2.6 2022年5月17日
0.2.5 2022年4月6日
0.1.2 2020年12月10日

#1606解析器实现

Download history 12/week @ 2024-04-20 5/week @ 2024-04-27 2/week @ 2024-05-04 7/week @ 2024-05-11 11/week @ 2024-05-18 7/week @ 2024-05-25 8/week @ 2024-06-01 11/week @ 2024-06-08 14/week @ 2024-06-15 9/week @ 2024-06-22 3/week @ 2024-06-29 8/week @ 2024-07-06 1/week @ 2024-07-13 61/week @ 2024-07-27 4/week @ 2024-08-03

66 每月下载量
用于 xlsx2csv

MIT/Apache

360KB
3K SLoC

OOXML - Rust中的Office OpenXML解析器

该项目最初是一个以Office Open XML为目标的私人项目,对Office Open XML的了解有限,使用时请谨慎!

Office Open XML,是由Microsoft开发的一种基于XML并以ZIP格式压缩的电子文件规范,支持文件、表格、备忘录、幻灯片等文件格式。

Office Open XML(非正式称为OOXML或Microsoft Open XML (MOX))是由Microsoft开发的一种压缩的XML文件格式,用于表示电子表格、图表、演示文稿和文字处理文档。该格式最初由Ecma(作为ECMA-376)以及后来的ISO和IEC(作为ISO/IEC 29500)标准化。

OOXML,正如其命名,试图成为一个纯Rust实现的Office Open XML解析器 - 在Rust中高效地读取和写入ooxml组件。但截至目前,仅支持xlsx解析。

简单来说;

examples/xlsx.rs中的示例代码

use ooxml::document::SpreadsheetDocument;

fn main() {
    let xlsx =
        SpreadsheetDocument::open("examples/simple-spreadsheet/data-image-demo.xlsx").unwrap();

    let workbook = xlsx.get_workbook();
    //println!("{:?}", xlsx);

    let _sheet_names = workbook.worksheet_names();

    for (sheet_idx, sheet) in workbook.worksheets().iter().enumerate() {
        println!("worksheet {}", sheet_idx);
        println!("worksheet dimension: {:?}", sheet.dimenstion());
        println!("---------DATA---------");
        for rows in sheet.rows() {
            // get cell values
            let cols: Vec<_> = rows
                .into_iter()
                .map(|cell| cell.value().unwrap_or_default())
                .collect();
            println!("{}", itertools::join(&cols, ","));
        }
    }
}

运行 cargo run --example xlsx

worksheet 0
worksheet dimension: Some((1, 1))
---------DATA---------

----------------------
worksheet 1
worksheet dimension: Some((4, 4))
---------DATA---------
name,age,birthday,last edited
bob,17,1983/12/12,2020/10/11 19:59
tom,18,1982/12/12,2020/10/11 19:59
cury,20,1980-12-12,2020-10-11 19:59
----------------------

库设计

主要思想来自DotNet OpenXML SDK

  1. 实现任何OOXML格式(docx/xlsx/pptx...)的OpenXML包约定,包括
    • 包的读取和写入
    • 内容类型解析
    • 关系通用类型
  2. 实现共享OpenXML部分
    • 内容类型
    • 核心属性
    • 应用程序属性
    • 文件属性
    • 嵌入式包
    • 图片
    • 主题
    • 样式
  3. 实现Excel/SpreadsheetML规范
    • 计算链
    • 图表工作表
    • 注释
    • 连接
    • 自定义属性
    • 客户XML映射
    • 对话框工作表
    • 绘图
    • 外部工作簿引用
    • 元数据
    • 数据透视表
    • 数据透视表缓存定义
    • 数据透视表缓存记录
    • 查询表
    • 共享字符串表
    • 共享工作簿修订记录
    • 共享工作簿用户数据
    • 单个单元格表定义
    • 表定义
    • 易变依赖
    • 工作簿
    • 工作表
  4. 其他 OpenXML 格式(docx, pptx)

代码库树结构如下。

src
├── document
│   ├── mod.rs
│   ├── presentation
│   │   └── mod.rs
│   ├── spreadsheet
│   │   ├── cell.rs
│   │   ├── chart.rs
│   │   ├── document_type.rs
│   │   ├── drawing.rs
│   │   ├── media.rs
│   │   ├── mod.rs
│   │   ├── shared_string.rs
│   │   ├── style.rs
│   │   ├── workbook.rs
│   │   └── worksheet.rs
│   └── wordprocessing
│       └── mod.rs
├── drawing
│   └── mod.rs
├── error.rs
├── lib.rs
├── math
│   └── mod.rs
└── packaging
    ├── app_property.rs
    ├── content_type.rs
    ├── custom_property.rs
    ├── element.rs
    ├── mod.rs
    ├── namespace.rs
    ├── package.rs
    ├── part
    │   ├── container.rs
    │   ├── mod.rs
    │   └── pair.rs
    ├── property.rs
    ├── relationship
    │   ├── mod.rs
    │   └── reference.rs
    ├── variant.rs
    ├── xml.rs
    └── zip.rs

对 Crate 的定义

主要设计原则是 一切类型化

  • :一个 是一个压缩的 OpenXML 文档,可以是文字处理/电子表格/演示文稿文档。
  • 元素:一个 元素 是一个 OpenXML 元素,表示每个 xml 中的数据细节。
  • 部分:一个 部分 是一组 元素 或纯数据,这些数据应该序列化到包中的一个文件中。
  • 组件:一个 组件 是行为与内部 OpenXML 东西的桥梁,包括 元素部分
  • 属性:一个 属性 表示元素的属性。
  • 文档:一个 文档 是真实文档的入口 组件,例如 电子表格文档 等。
  • 关系:一个 关系 是元素与其他资源从 部分 的链接关系。

数据流或创建文档将如下所示。

Document -> Package : open/parse from
Package -> Parts : parse to parts
Parts -> Components: build components tree
Components -> Elements: elements one-to-one map
Elements -> Components: elements changes
Components -> Parts: components write back
Parts -> Package: serialize to package
Package <- Document: flush, save or others

Document -> Components: create new document. add or remove components
Components <-> Elements: operations
Components -> Parts: component add/remove
Parts -> Package: serialize to package
Document -> Package: flush, save or others

初始化实现功能

  • OPC 解析,包括读取和写入
  • 共享组件
    • 内容类型
    • 核心属性
    • 应用程序属性
    • 文件属性(不在计划中)
    • 嵌入式包(不在计划中)
    • 图片
    • 主题
    • 样式
  • 电子表格 ML
    • 工作簿
    • 工作表

待办事项

  • 为 OpenXML 元素创建标记特征,使其更通用。
  • 在 xml 部分中使用 minidom,跟踪更改并将其写回 DOM 树。
  • 延迟解析一些 OpenXML 部分以加快首次启动速度。
  • 实现组件生成的辅助宏。

Tokei - 2020-11-04-11:35:51

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 Markdown                1          272            0          230           42
 Plain Text              1            1            0            1            0
 TOML                    1           23           21            1            1
 XML                    52          164          164            0            0
-------------------------------------------------------------------------------
 Rust                   34         2721         2189          194          338
 |- Markdown            14          106            7           90            9
 (Total)                           2827         2196          284          347
===============================================================================
 Total                  89         3287         2381          516          390
===============================================================================

概念

Office Open XML 或 OpenXML

Office Open XML(非正式称为OOXML或Microsoft Open XML (MOX))是由Microsoft开发的一种压缩的XML文件格式,用于表示电子表格、图表、演示文稿和文字处理文档。该格式最初由Ecma(作为ECMA-376)以及后来的ISO和IEC(作为ISO/IEC 29500)标准化。

Microsoft Office 2010 为 ECMA-376 提供读取支持,为 ISO/IEC 29500 过渡版提供读取/写入支持,并为 ISO/IEC 29500 严格版提供读取支持。Microsoft Office 2013 和 Microsoft Office 2016 还额外支持 ISO/IEC 29500 严格版的读取和写入。虽然从 Office 2013 开始对 ISO/IEC 29500 严格版提供完全的读取/写入支持,但由于持续的互操作性担忧,Microsoft 尚未将严格非过渡版或原始标准作为默认文件格式实施。

OpenXML 包约定

Open Packaging Conventions (OPC) 是一种容器文件技术,最初由 Microsoft 创建,用于存储一个组合的 XML 和非 XML 文件,这些文件共同形成一个单一实体,例如 Open XML Paper Specification (OpenXPS) 文档。基于 OPC 的文件格式结合了在文档中保留独立文件实体完整性的优点,与正常使用 XML 相比,文件大小小得多。

标准 ECMA-376

标准 ECMA-376 - Office Open XML 文件格式标准。

第 1 版(2006 年 12 月),第 2 版(2008 年 12 月),第 3 版(2011 年 6 月),第 4 版(2012 年 12 月)和第 5 版(第 3 部分,2015 年 12 月;第 1 部和第 4 部分,2016 年 12 月)。

版本下载

目前是第 4 版,技术上与 ISO/IEC 29500 对齐。第 5 版正在进展中。有一个 Office Open XML 概述 介绍 pdf 文件。

电子表格 ML

SpreadsheetML 或 .xlsx 文件是一个包含多个 "部分"(通常是 UTF-8 或 UTF-16 编码)或 XML 文件的压缩文件(一个包)。该包还可以包含其他媒体文件,如图像。结构根据 ECMA-376 标准 OOXML 的第 2 部分的开放打包约定组织。

您可以通过简单地解压缩 .xlsx 文件来查看文件结构和组成 SpreadsheetML 文件的文件。

├── [Content_Types].xml
├── docProps
│   ├── app.xml
│   ├── core.xml
│   └── custom.xml
├── _rels
└── xl
    ├── charts
    │   ├── chart1.xml
    │   ├── colors1.xml
    │   ├── _rels
    │   │   └── chart1.xml.rels
    │   └── style1.xml
    ├── drawings
    │   ├── drawing1.xml
    │   ├── drawing2.xml
    │   └── _rels
    │       ├── drawing1.xml.rels
    │       └── drawing2.xml.rels
    ├── media
    │   └── image1.png
    ├── _rels
    │   └── workbook.xml.rels
    ├── sharedStrings.xml
    ├── styles.xml
    ├── theme
    │   └── theme1.xml
    ├── workbook.xml
    └── worksheets
        ├── _rels
        │   ├── sheet1.xml.rels
        │   └── sheet2.xml.rels
        ├── sheet1.xml
        └── sheet2.xml

部分的数量和类型将根据工作表中的内容而变化,但总会包含一个 [Content_Types].xml、一个或多个关系部分、一个工作簿部分和至少一个工作表。工作表部分包含电子表格的核心数据,详情请参考 xslx 内容概述

资源

  1. 维基百科 Office OpenXML:[英文](https://en.wikipedia.org/wiki/Office_Open_XML),[中文](https://zh.wikipedia.org/wiki/Office_Open_XML)。
  2. Microsoft [DotNet OpenXML SDK](https://docs.microsoft.com/en-us/dotnet/api/overview/openxml/?view=openxml-2.8.1) 文档和 [源代码](https://github.com/OfficeDev/Open-XML-SDK/)。
  3. 维基百科 [OpenXML 打包约定](https://en.wikipedia.org/wiki/Open_Packaging_Conventions) - [开放打包约定](https://zh.wikipedia.org/wiki/%E5%BC%80%E6%94%BE%E6%89%93%E5%8C%85%E7%BA%A6%E5%AE%9A)。
  4. 什么是 OOXML:[http://officeopenxml.com/](http://officeopenxml.com/)
  5. SpreadsheetML:[http://officeopenxml.com/anatomyofOOXML-xlsx.php](http://officeopenxml.com/anatomyofOOXML-xlsx.php)
  6. Rust [quick-xml](https://crates.org.cn/crates/quick-xml) [文档](https://docs.rs/quick-xml/0.20.0)。
  7. Rust [docx-rs](https://crates.org.cn/crates/docx-rs) [文档](https://docs.rs/docx-rs) 和 [GitHub 上的源代码](https://github.com/bokuweb/docx-rs)。
  8. Go Excel 文件解析器 [excelize](https://github.com/360EntSecGroup-Skylar/excelize)。
  9. 标准 ECMA-376.

依赖项

~14MB
~272K SLoC