8.5 KiB
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()))。
注意事项
-
编码问题
- 推荐使用 UTF-8 编码保存 Excel 中的文本
- 若出现乱码,请检查
encoding参数
-
安全性警告
include()函数使用exec,不要用于不可信输入
-
版本兼容性
- 使用
xlrd,注意其对.xlsx的支持有限(建议使用xlrd>=1.2.0或考虑迁移到openpyxl)
- 使用
-
性能
- 适合中小规模配置文件,不适合大数据量导入
-
错误处理
- 部分异常被捕获并打印,但不会中断程序
已知限制
- 仅支持读取,不支持写入
- 日期仅提取年月日,忽略时分秒
__dict__和__list__结构需要严格对齐exec使用存在安全隐患lrtrim来自外部模块,需确保安装
未来改进建议
- 替换
exec为更安全的路径访问机制(如dpath或递归查找) - 支持更多数据类型(如布尔、JSON)
- 添加日志系统代替
print - 支持
openpyxl以兼容现代 Excel 格式 - 提供导出为 JSON/YAML 的接口
版权与许可
© 2025 作者保留所有权利。
可用于内部项目,禁止商业分发。
✅ 文档更新时间:2025年4月5日