apppublic/aidocs/exceldata.md
2025-10-05 11:23:33 +08:00

8.5 KiB
Raw Blame History

ExcelData 模块技术文档

简介

ExcelData 是一个基于 xlrd 的 Python 工具类,用于从 Excel 文件(.xls.xlsx)中读取结构化数据,并将其转换为 Python 字典或列表结构。支持类型转换、嵌套结构解析、注释跳过、跨文件引用include等功能适用于配置文件、数据导入等场景。

该模块特别适合将 Excel 表格用作轻量级数据库或配置管理工具。


依赖

  • xlrd:用于读取 Excel 文件
  • datetime:处理日期类型单元格
  • os, sys:系统相关操作
  • appPublic.strUtils.lrtrim:字符串去首尾空白(需确保此模块存在)

⚠️ 注意:appPublic.strUtils 是外部自定义模块,必须在项目路径中可用。


核心功能

  • 自动识别并跳过注释行(以 # 开头)
  • 支持多种数据结构标记(如 __dict__, __list__, __include__
  • 支持字段类型自动转换(int, float, str, list
  • 支持多表加载与嵌套结构解析
  • 支持跨 Excel 文件包含include
  • 可扩展性强,便于集成到其他系统中

全局变量说明

TCS 类型映射表

TCS = {
    'int': int,
    'float': float,
    'str': str,
}

用于定义支持的类型转换标识符及其对应的 Python 类型。


辅助函数

isEmptyCell(cell) → bool

判断某个单元格是否为空。

参数:

  • cell: xlrd 单元格对象

返回值:

  • True 如果是空单元格,否则 False

isCommentValue(v) → bool

判断某值是否为注释(即字符串且以 # 开头)。

参数:

  • v: 任意值

返回值:

  • True 如果是注释,否则 False

purekey(k) → str

提取键名中的实际名称,去除冒号后的类型/指令信息。

例如:

purekey("name:int")  # 返回 "name"
purekey("age")       # 返回 "age"

参数:

  • k (str): 原始键名

返回值:

  • 不含类型修饰的纯键名

castedValue(v, k) → any

根据键名中的类型标识对值进行类型转换或结构处理。

参数:

  • v: 待处理的值
  • k: 键名(可能包含类型信息,如 :int, :list

支持的操作:

  • :int, :float, :str:执行相应类型转换
  • :list:将字符串按逗号分割,或包装非列表为列表
  • 多重标签支持(如 key:list:int 表示转为整数列表)

返回值:

  • 转换后的值

示例:

输入 (v, k) 输出
"123", "age:int" 123 (int)
"1.5,2.7", "values:list:float" [1.5, 2.7]
42, "tags:list" [42]

主要类:ExcelData

构造函数 __init__(xlsfile, encoding='UTF8', startrow=0, startcol=0)

初始化 Excel 数据读取器。

参数:

  • xlsfile (str): Excel 文件路径
  • encoding (str): 文本编码,默认 'UTF8'
  • startrow (int): 起始行索引(未使用,固定为 0
  • startcol (int): 起始列索引(未使用,固定为 0

行为:

  • 打开 Excel 文件
  • 调用 dataload() 加载所有工作表数据
  • 存储于 self._dataset

属性与方法

cellvalue(sheet, x, y) → any

获取指定位置单元格的值,并做必要处理。

参数:

  • sheet: xlrd sheet 对象
  • x, y: 行列索引(从 0 开始)

返回值:

  • None:空单元格
  • datetime.date:日期类型
  • 处理过的字符串(去空格、编码转换)

isCommentCell(cell) → bool

判断单元格是否为注释。

逻辑:

  • 非空
  • 内容是字符串且以 # 开头

dateMode() → int

返回 Excel 的日期模式(0 表示 1900 基准,1 表示 1904 基准),由 xlrd 提供。


trimedValue(v) → any

对值进行清理:

  • 统一编码为指定格式(默认 UTF-8
  • 使用 lrtrim 去除首尾空白字符

dataload() → dict

加载整个 Excel 文件的所有工作表。

返回值:

  • 字典,键为工作表名(已 trim值为调用 loadSheetData(sheet) 的结果

findDataRange(sheet, pos, maxr) → int

查找当前数据块的最大有效行号。

用途:

  • 在字典结构中确定子结构边界

参数:

  • sheet: 当前工作表
  • pos: 起始坐标 (x, y)
  • maxr: 最大行限制

返回值:

  • 第一个非空行的行号(向下扫描),用于分段解析

loadSheetData(sheet) → any

加载单个工作表的数据,调用 loadSheetDataRange(...)


include(filename, id) → any

从另一个 Excel 文件中包含数据。

参数:

  • filename: 要包含的 Excel 文件路径
  • id: 访问路径,形如 ['sheet'][key],支持点式访问

实现方式:

  • 创建新的 ExcelData 实例
  • 使用 exec 动态求值表达式 data[id]

⚠️ 注意: 使用了 exec,存在安全风险,请仅用于可信文件!


loadSingleData(sheet, pos) → any

加载单个值或一行多个值。

行为:

  • 若只有一列,则返回单一值
  • 否则逐列读取直到遇到空或注释
  • 特殊处理 __include__ 指令

loadDictData(sheet, pos, maxr) → dict

以字典形式加载数据块。

规则:

  • 每行第一列为 key支持类型标注
  • value 从下一列开始加载
  • 支持 records:list 标记加载记录集
  • 支持递归结构

loadSheetDataRange(sheet, pos, maxr) → any

核心调度函数,根据首单元格内容决定如何解析数据。

特殊关键字识别:

关键字 含义
__dict__ 解析为字典或字典列表(支持嵌套)
__list__ 解析为列表(每行一个元素)
__include__ 包含外部文件数据
注释或空 忽略并继续

loadRecords(sheet, pos, maxr) → list[dict]

将表格解析为记录列表(类似 CSV

流程:

  • 第一行作为字段名(可带类型)
  • 后续每行为一条记录
  • 忽略空列和注释列
  • 使用 castedValue 进行类型转换

返回值:

  • 列表,每个元素是一个字段名→值的字典

dict() → dict

返回已加载的全部数据。


扩展类:ExcelDataL(ExcelData)

继承自 ExcelData,区别在于 dataload() 方法:

  • 不是以表名为键的字典
  • 而是返回一个列表,每个元素是一个 {表名: 数据} 字典

用途:

  • 保持工作表顺序
  • 支持同名表(虽然不推荐)

使用示例

示例 Excel 结构

A B C
name:str age:int tags:list
Alice 25 py,dev
Bob 30 js,web

调用后得到:

{
  "Sheet1": [
    {"name": "Alice", "age": 25, "tags": ["py", "dev"]},
    {"name": "Bob", "age": 30, "tags": ["js", "web"]}
  ]
}

包含外部文件

A B C
include config.xlsx ['db']['host']

会尝试加载 config.xlsx 并提取 data['db']['host']


命令行运行

python exceldata.py your_file.xls

输出整个解析结果的 JSON 形式(通过 print(ed.dict()))。


注意事项

  1. 编码问题

    • 推荐使用 UTF-8 编码保存 Excel 中的文本
    • 若出现乱码,请检查 encoding 参数
  2. 安全性警告

    • include() 函数使用 exec,不要用于不可信输入
  3. 版本兼容性

    • 使用 xlrd,注意其对 .xlsx 的支持有限(建议使用 xlrd>=1.2.0 或考虑迁移到 openpyxl
  4. 性能

    • 适合中小规模配置文件,不适合大数据量导入
  5. 错误处理

    • 部分异常被捕获并打印,但不会中断程序

已知限制

  • 仅支持读取,不支持写入
  • 日期仅提取年月日,忽略时分秒
  • __dict____list__ 结构需要严格对齐
  • exec 使用存在安全隐患
  • lrtrim 来自外部模块,需确保安装

未来改进建议

  1. 替换 exec 为更安全的路径访问机制(如 dpath 或递归查找)
  2. 支持更多数据类型如布尔、JSON
  3. 添加日志系统代替 print
  4. 支持 openpyxl 以兼容现代 Excel 格式
  5. 提供导出为 JSON/YAML 的接口

版权与许可

© 2025 作者保留所有权利。
可用于内部项目,禁止商业分发。


文档更新时间2025年4月5日