CoreXLSX

使用纯 Swift 编写的 Excel 电子表格 (XLSX) 格式解析器

Build Status Version License Platform Coverage

CoreXLSX 是一个专注于表示基于 XML 的 XLSX 电子表格格式底层结构的库。它允许您打开扩展名为 .xlsx 的电子表格存档,并将其内部结构映射到直接在 Swift 中表达的模型类型。

需要注意的是,此库仅为 .xlsx 格式提供只读支持。由于旧的传统 .xls 电子表格格式具有完全不同的内部结构,如果您需要处理该类型的文件,请参考其他库

如果您的 .xlsx 文件使用 ECMA-376 agile 加密(这似乎是最流行的变体),请查看 CryptoOffice 库。

自动生成的文档可在 我们的 GitHub Pages 上找到。

加入我们的 Discord,提出任何问题和进行友好的交流。

示例

要运行示例项目,请克隆仓库,并首先从 Example 目录运行 pod install

CoreXLSX 中的模型类型直接映射 XLSX 格式的内部结构,并对一些属性应用了更合理的命名。API 非常简单

import CoreXLSX

let filepath = "./categories.xlsx"
guard let file = XLSXFile(filepath: filepath) else {
  fatalError("XLSX file at \(filepath) is corrupted or does not exist")
}

for wbk in try file.parseWorkbooks() {
  for (name, path) in try file.parseWorksheetPathsAndNames(workbook: wbk) {
    if let worksheetName = name {
      print("This worksheet has a name: \(worksheetName)")
    }

    let worksheet = try file.parseWorksheet(at: path)
    for row in worksheet.data?.rows ?? [] {
      for c in row.cells {
        print(c)
      }
    }
  }
}

这将打印给定 XLSX 文件中每个工作表的原始单元格数据。请参考 Worksheet 模型以获取您可能需要从解析文件中读取的更多属性。

单元格引用

您不应通过 cells 数组中的索引来寻址单元格。每个单元格都有一个 reference 属性,您可以读取该属性以了解给定单元格的确切位置。CellReference 结构上的相应属性为您提供单元格的精确位置。

空单元格

.xlsx 格式明确区分空单元格和单元格的缺失。如果您在迭代 cells 数组时没有获得单元格或行,则表示您的文档中没有这样的单元格或行。您的 .xlsx 文档首先应该写入空单元格和行,您才能读取它们。

进行这种区分使格式更有效率,特别是对于稀疏电子表格。如果您有一个包含单个单元格 Z1000000 的电子表格,它不会包含数百万个空单元格和一个具有值的单元格。该文件仅存储单个单元格,这使得稀疏电子表格可以快速保存和加载,并且占用更少的文件系统空间。

通过单元格引用查找单元格

鉴于 .xlsx 格式存储单元格的方式,您可能需要迭代所有单元格并构建从单元格引用到实际单元格值的自己的映射。CoreXLSX 库目前不会自动执行此操作,如果需要,您必须实现自己的映射。欢迎您提交一个 pull request,在解析过程中添加此类功能作为可选步骤。

共享字符串

电子表格内部的字符串通常表示为在多个工作表之间共享的字符串。要从单元格解析字符串值,您应该在 Cell 上使用 stringValue(_: SharedStrings) 函数,并在 XLSXFile 上使用 parseSharedString()

以下是如何获取例如列 “C” 中的所有字符串的方法

if let sharedStrings = try file.parseSharedStrings() {
  let columnCStrings = worksheet.cells(atColumns: [ColumnReference("C")!])
    .compactMap { $0.stringValue(sharedStrings) }
}

要从单元格解析日期值,请使用 Cell 类型的 dateValue 属性

let columnCDates = worksheet.cells(atColumns: [ColumnReference("C")!])
  .compactMap { $0.dateValue }

同样,要解析富文本字符串,请使用 richStringValue 函数

if let richStrings = try file.parseSharedStrings() {
  let columnCRichStrings = worksheet.cells(atColumns: [ColumnReference("C")!])
    .compactMap { $0.richStringValue(sharedStrings) }
}

样式

自 0.5.0 版本起,您可以使用新的 parseStyles() 函数从存档中解析样式信息。请参考 Styles 模型以获取更多详细信息。您还应该注意,并非所有 XLSX 文件都包含样式信息,因此您应该准备好处理在这种情况下从 parseStyles() 函数抛出的错误。

这是一个获取已使用字体列表的简短示例

let styles = try file.parseStyles()
let fonts = styles.fonts?.items.compactMap { $0.name?.value }

要获取给定单元格的格式,请使用 format(in:)font(in:) 函数,并将 parseStyles 的结果传递给它

let styles = try file.parseStyles()
let format = worksheet.data?.rows.first?.cells.first?.format(in: styles)
let font = worksheet.data?.rows.first?.cells.first?.font(in: styles)

报告兼容性问题

如果您遇到无法解析的文件,请提交 issue 并发布确切的错误消息。由于使用了标准的 Swift Codable 协议,因此会生成详细的错误信息,列出缺少的属性,因此可以轻松将其添加到模型中,从而实现更广泛的格式支持。附加无法解析的文件也将极大地帮助诊断问题。如果这些文件包含任何敏感数据,我们建议使用与生成原始文件相同的工具混淆或生成虚假数据,前提是问题仍然可以以这种方式重现。

如果无法附加整个文件,请尝试将足够大的值(通常介于 10 到 20 之间效果良好)传递给 XLSXFile 初始化程序的 errorContextLength 参数。这将把失败的 XML 代码段与抛出错误的调试描述捆绑在一起。报告问题时,如果可能,请同时附加完整的调试描述。

它是如何工作的?

由于每个 XLSX 文件都是 XML 文件的 zip 存档,CoreXLSX 使用 XMLCoder 库和标准的 Codable 协议将 XML 节点和属性映射到纯 Swift 结构体中。ZIPFoundation 用于 zip 存档的内存解压缩。详细描述可在此处找到

要求

Apple 平台

Linux

安装

Swift 包管理器

Swift 包管理器是用于管理 Swift 代码分发的工具。它与 Swift 构建系统集成,以自动化在所有平台上下载、编译和链接依赖项的过程。

一旦您设置好 Swift 包,添加 CoreXLSX 作为依赖项就像将其添加到 Package.swiftdependencies 值中一样简单。

dependencies: [
  .package(url: "https://github.com/CoreOffice/CoreXLSX.git",
           .upToNextMinor(from: "0.14.1"))
]

如果您在 Xcode 构建的应用程序中使用 CoreXLSX,您也可以使用 Xcode 的 GUI 将其添加为直接依赖项。

CocoaPods

CoreXLSX 在 Apple 平台上可通过 CocoaPods 获得。要安装它,只需将 pod 'CoreXLSX', '~> 0.14.1' 添加到您的 Podfile 中,如下所示

source 'https://github.com/CocoaPods/Specs.git'
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
use_frameworks!
target '<Your Target Name>' do
  pod 'CoreXLSX', '~> 0.14.1'
end

贡献

开发工作流程

在 macOS 上,开始处理该项目最简单的方法是在 Xcode 11 或更高版本中打开 Package.swift 文件。有一个广泛的测试套件,它既测试文件的端到端,也测试隔离的代码片段及其对应的模型值。

如果您不喜欢使用 Xcode,该项目完全支持 SwiftPM 以及使用 swift buildswift test 的常用工作流程,否则请将其报告为 bug

编码风格

本项目使用 SwiftFormatSwiftLint 来强制执行格式化和编码风格。我们鼓励您在存储库的本地克隆中以最适合您的方式手动或自动运行 SwiftFormat,例如通过 Xcode 扩展构建阶段git pre-commit hook 等。

为了保证这些工具在您在 macOS 上提交更改之前运行,我们建议您运行一次以设置 pre-commit hook

brew bundle # installs SwiftLint, SwiftFormat and pre-commit
pre-commit install # installs pre-commit hook to run checks before you commit

有关更多详细信息和其他平台的安装说明,请参阅 pre-commit 文档页面

SwiftFormatSwiftLint 也在 CI 上为每个 PR 运行,因此 CI 构建可能会因格式或风格不一致而失败。我们要求所有 PR 的 CI 构建都通过才能合并。

行为准则

本项目遵守《贡献者盟约行为准则》。参与本项目,即表示您需要遵守此准则。请向 coreoffice@desiatov.com 报告不可接受的行为。

许可证

CoreXLSX 在 Apache 2.0 许可证下可用。有关更多信息,请参阅 LICENSE 文件。