8.8 KiB
技术文档:xlsx_data_processor.py
概述
该模块提供了一个用于处理 Excel(.xlsx)文件和结构化数据的工具集,支持从 .xlsx 文件中读取数据并将其转换为结构化的字典对象。它特别适用于管理具有特定格式规范的 CRUD(创建、读取、更新、删除)配置表,并能自动解析字段类型、主键、外键、索引等元信息。
模块主要功能包括:
- 从
.xlsx文件加载数据并按工作表组织。 - 支持自定义字段类型的自动转换(如
int,float,json等)。 - 支持扩展的数据格式(如
cruddata,xlsxdata)通过字符串协议调用。 - 提供对特殊格式的 CRUD 配置文件的支持(包含
summary,fields,validation等 sheet)。 - 命令行接口,可批量合并多个数据源(Excel 和参数)输出 JSON。
依赖库
import os
import sys
from traceback import print_exc
from openpyxl import load_workbook
from appPublic.myjson import loadf, dumpf, dumps
from appPublic.dictObject import DictObject
⚠️ 注意:
appPublic是一个自定义公共库,需确保已安装或路径正确。
核心类与函数说明
1. TypeConvert 类
负责将原始值根据指定类型进行安全转换。
方法列表:
| 方法 | 描述 |
|---|---|
conv(typ, v) |
根据类型名 typ 调用对应的转换方法(如 to_int),若无则返回原值。 |
to_int(v) |
转换为整数,失败返回 0。 |
to_float(v) |
转换为浮点数,失败返回 0.0。 |
to_str(v) |
转换为字符串,失败返回空串 ''。 |
to_json(v) |
将字符串解析为 JSON 对象,空字符串保持不变,失败返回原值。⚠️ 存在 bug:应使用 loads 但代码中写成了 loads(v) 实际未导入。 |
to_date(v), to_time(v), to_timestamp(v) |
占位方法,直接返回原值(未来可扩展)。 |
to_cruddata(v) |
解析形如 "cruddata:\"filename\".property" 的字符串,动态加载 CRUDData 并执行属性/方法访问。 |
to_xlsxdata(v) |
类似 to_cruddata,但用于普通 XLSXData 对象。 |
✅ 示例输入:
"cruddata:\"user.xlsx\".users"→ 加载user.xlsx并获取其users表数据。
❗ Bug 提示:
to_json中使用了未定义的loads函数,应改为from json import loads或使用dumps所属模块中的loads。
2. CRUDException(Exception) 类
自定义异常类,用于报告 .xlsx 文件处理过程中的错误。
属性:
xlsfile: 出错的文件名errmsg: 错误描述
__str__() 返回格式:
filename:<文件名> error:<错误信息>
3. XLSXData 类
通用 .xlsx 文件读取器,将每个工作表解析为记录列表,并封装成 DictObject。
构造函数:__init__(xlsxfile, book=None)
xlsxfile: Excel 文件路径book: 可选的已打开的Workbook对象(用于性能优化或复用)
主要方法:
| 方法 | 功能 |
|---|---|
_read() |
内部方法,遍历所有 sheet 并调用 readRecords() 构建 self.data。 |
get_data() |
返回最终解析后的数据对象(DictObject)。 |
readRecords(name, sheet) |
读取单个 sheet 数据: - 第一行作为字段定义(格式: 字段名:类型)- 后续行为数据行 - 使用 TypeConvert 进行类型转换- 返回 {name: [DictObject(...), ...]} |
getFieldNames(row) |
处理首行字段: - 若为空则命名为 F_i- 分割 name:type 形式,缺失类型设为 None- 返回 [ [字段名, 类型], ... ] |
📌 字段命名规则示例:
id:int→ 名称id,类型intusername→ 名称username,类型None- 空单元格 → 自动命名为
F_0,F_1...
4. CRUDData(XLSXData) 类
继承自 XLSXData,专用于处理符合 CRUD 元数据规范的 .xlsx 文件。
规范要求:
必须包含以下三个工作表:
summary: 表基本信息(如主键)fields: 字段定义列表validation: 验证规则(外键、索引等)
类方法:isMe(book)
判断给定 workbook 是否满足 CRUDData 格式(检查是否存在上述三个 sheet)。
重写 _read() 方法流程:
- 调用父类
_read()解析所有 sheet。 - 验证
summary,fields,validation存在且唯一。 - 执行元数据转换:
convPrimary(): 解析主键字段(逗号分隔)convForeignkey(): 解析外键规则(格式:table:value:title)convIndex(): 解析索引定义(格式:idx_type:key1,key2)check_codes_fields(): 验证codes表中的字段是否存在于fields
辅助方法:
| 方法 | 功能 |
|---|---|
check_field(fieldname) |
检查字段是否在 fields 表中存在 |
getFieldByNmae(fields, name) |
获取指定名称的字段定义(拼写错误:Nmae 应为 Name)❗ |
getFKs(validation) |
提取所有外键规则(oper == 'fk') |
getIDXs(validation) |
提取所有索引规则(oper == 'idx') |
⚠️ Bug 提示:
getFieldByNmae函数名拼写错误,可能导致调用失败。getFKs中条件判断写成了'oepr'而非'oper',导致无法识别外键。
5. xlsxFactory(xlsxfilename) 函数
根据文件内容自动选择合适的类实例化(工厂模式)。
流程:
- 打开
.xlsx文件。 - 遍历
XLSXData的所有子类(递归查找),调用isMe(book)判断是否匹配。 - 匹配成功则返回
CRUDData实例,否则返回默认XLSXData实例。 - 异常捕获并打印堆栈。
✅ 支持插件式扩展:可通过新增子类实现其他专用格式识别。
6. ValueConvert(s) 函数
解析特殊前缀字符串,支持外部资源引用。
| 前缀 | 行为 |
|---|---|
xlsfile::path/to/file.xlsx |
使用 xlsxFactory 加载并返回 .get_data() |
jsonfile::path/to/data.json |
使用 loadf() 读取 JSON 文件 |
| 其他 | 直接返回原字符串 |
7. paramentHandle(ns) 函数
对参数字典中的每个值应用 ValueConvert,实现参数注入时的自动资源加载。
✅ 示例:
python script.py data=xlsfile::config.xlsx user=jsonfile::user.json
→ 自动加载 Excel 和 JSON 文件内容。
主程序入口(if __name__ == '__main__':)
支持命令行运行,用法如下:
参数格式:
key=value:设置命名参数(支持xlsfile::,jsonfile::)filepath:直接加载数据文件(仅限.xlsx,.xls)
执行流程:
- 解析命令行参数,分离
ns(命名空间)和datafiles(文件列表)。 - 处理
ns中的值(调用paramentHandle)。 - 遍历
datafiles,使用xlsxFactory加载每个 Excel 文件。 - 合并所有数据到
retData。 - 输出合并后的 JSON 结果(使用
dumps格式化)。
示例命令:
python xlsx_data_processor.py \
config=xlsfile::app_config.xlsx \
user=jsonfile::default_user.json \
roles.xlsx \
permissions.xlsx
输出结果为整合所有来源数据的 JSON 对象。
已知问题与改进建议
| 问题 | 描述 | 建议修复 |
|---|---|---|
to_json 使用 loads 未定义 |
导致 JSON 解析失败 | 改为 from json import loads 或使用 dumps.loads() |
getFieldByNmae 拼写错误 |
方法名错误 | 更正为 getFieldByName |
getFKs 条件判断错误 |
'oepr' == 'fk' 永不成立 |
改为 'oper' |
check_field(f for f in ...) |
语法错误,不能传生成器 | 改为循环逐一检查每个字段 |
vs < 3 在 split 后无效 |
vs 是 list,比较 < 3 不合理 |
应改为 len(vs) < 3 |
to_cruddata / to_xlsxdata 中 vs[2] is None |
split 不会返回 None 元素 |
应改为 len(vs) <= 2 判断是否有命令部分 |
使用示例
示例 Excel 结构(users.xlsx)
Sheet: users
id:int,name:str,age:int
1,Alice,25
2,Bob,30
Sheet: summary
table:primary
users:id
Sheet: fields
name,type,desc
id,int,用户ID
name,str,用户名
age,int,年龄
调用方式:
d = xlsxFactory('users.xlsx')
data = d.get_data()
print(data.users[0].name) # 输出: Alice
print(data.summary[0].primary) # 输出: ['id']
总结
本模块是一个轻量级但功能丰富的 .xlsx 数据处理器,适合用于配置中心、元数据管理、自动化脚本等场景。结合自定义前缀协议和工厂模式,具备良好的扩展性。
尽管存在少量 bug 和命名问题,整体设计清晰,层次分明,易于维护和二次开发。
作者:Auto-generated Technical Documentation
版本:1.0
最后更新:2025-04-05