# PinMAP → PinList 转换器 — 全局架构设计 > **版本**: v1.0 > **日期**: 2026-05-25 > **架构师**: 脚本架构师 (Script Architect) > **状态**: 待审批 --- ## 1. 项目概述 ### 1.1 背景 将 Excel 格式的 **PinMAP** 文件(方形封装引脚布局图)自动转换为 **PinList** 格式(引脚序号列表),消除手动抄录的低效与错误风险。 ### 1.2 核心规则 - PinMAP 为方形/长方形结构,引脚沿四条边分布,左上角为 1 脚,**逆时针**排序 - 左上角 = 1 脚,右上角 = 上边最后一个脚,右下角 = 下边最后一个脚,左下角 = 左边最后一个脚 - 四个角点被相邻两边共享(不重复计数) ### 1.3 约束 | 约束项 | 说明 | |--------|------| | 运行平台 | Windows | | 技术栈 | Python 标准库,**零第三方依赖** | | 输入格式 | `.xls`(必须支持)、`.xlsx`(优先支持) | | 输出格式 | `.xlsx` 仅 | | 交互方式 | 命令行 + 文件选择对话框 | --- ## 2. 技术选型 ### 2.1 为什么不用 openpyxl / xlrd? 项目明确要求 **无第三方依赖**,因此必须使用 Python 标准库自行实现 Excel 读写。 ### 2.2 XLS 读取 — BIFF8 二进制解析 `.xls` 是 Microsoft **BIFF8** 二进制格式(复合文档 OLE2 容器)。 **实现策略**: ``` 1. 使用 struct 模块解析 OLE2 复合文档头 2. 解析 FAT(文件分配表)定位 MiniFAT 和目录流 3. 定位 Workbook 流,读取 BIFF8 记录序列 4. 关键记录类型: - 0x0009 (BOF) → 块起始标记 - 0x00FD (LABELSST) → 共享字符串表中的文本单元格 - 0x0006 (FORMULA) → 公式/数值单元格 - 0x0203 (NUMBER) → 数值单元格 - 0x000C (RK) → RK 数值(压缩整数/浮点) - 0x000D (RString) → 内联字符串 - 0x00FC (STRING) → 字符串结果 - 0x0034 (SST) → 全局共享字符串表 - 0x0042 (BOUNDSHEET) → 工作表信息 5. 提取每个单元格的 (行, 列, 值) 三元组 ``` **复杂度评估**:中等。BIFF8 是固定长度记录流,struct 解析直接。需处理 Unicode 编码(BIFF8 默认 UTF-16LE,部分兼容 ASCII)。 ### 2.3 XLSX 读取 — ZIP + XML `.xlsx` 本质是 ZIP 压缩包,内部为 Office Open XML (OOXML)。 **实现策略**: ```python import zipfile import xml.etree.ElementTree as ET 1. zipfile.ZipFile 打开 .xlsx 2. 读取 [Content_Types].xml 确认结构 3. 读取 xl/workbook.xml 获取工作表关系 4. 读取 xl/worksheets/sheet1.xml 获取单元格数据 5. 读取 xl/sharedStrings.xml 获取共享字符串表 6. 解析单元格坐标(如 "A2" → 列A行2)和值类型 ``` **复杂度评估**:低。zipfile 和 xml.etree 均为标准库,XML 结构规范清晰。 ### 2.4 XLSX 写入 — ZIP + XML 生成 **实现策略**: ```python import zipfile import xml.etree.ElementTree as ET from io import BytesIO 1. 构建 OOXML 目录结构: [Content_Types].xml _rels/.rels xl/workbook.xml xl/worksheets/sheet1.xml xl/sharedStrings.xml xl/_rels/workbook.xml.rels 2. 使用 zipfile.ZipFile 写入(ZIP_DEFLATED) 3. 关键 XML 构建: - sharedStrings.xml: 所有唯一字符串的 SST - sheet1.xml: 单元格坐标 + si (SST index) 引用 - workbook.xml: 工作表引用 - [Content_Types].xml: MIME 类型声明 ``` **复杂度评估**:低。XML 结构固定,模板化生成即可。 ### 2.5 技术选型总结 | 操作 | 格式 | 标准库模块 | 难度 | |------|------|-----------|------| | 读取 | xls | `struct` + 手动 OLE2/BIFF8 解析 | 中 | | 读取 | xlsx | `zipfile` + `xml.etree.ElementTree` | 低 | | 写入 | xlsx | `zipfile` + `xml.etree.ElementTree` | 低 | | 文件选择 | — | `tkinter.filedialog` | 低 | --- ## 3. 模块划分 ``` pinmap-to-pinlist/ ├── Code/ │ ├── src/ │ │ ├── main.py # 入口:流程编排 │ │ ├── file_selector.py # 模块1:文件选择 │ │ ├── xls_reader.py # 模块2a:XLS 解析引擎 │ │ ├── xlsx_reader.py # 模块2b:XLSX 解析引擎 │ │ ├── pinmap_parser.py # 模块3:PinMAP 结构解析 │ │ ├── validator.py # 模块4:数据验证 │ │ ├── pinlist_generator.py # 模块5:PinList 生成 │ │ └── xlsx_writer.py # 模块6:XLSX 输出引擎 │ └── docs/ │ └── architecture-design.md ├── Test/ └── Releases/ ``` ### 3.1 模块职责 #### 模块1:`file_selector` — 文件选择 ```python def select_file() -> str | None: """弹出文件选择对话框,返回选中文件路径或 None(取消)""" ``` - 使用 `tkinter.filedialog.askopenfilename` - 文件类型过滤:`*.xls;*.xlsx` - 无 GUI 环境时回退到命令行参数 #### 模块2a:`xls_reader` — XLS 解析引擎 ```python class XLSReader: def __init__(self, filepath: str) def read_all_cells(self) -> dict[tuple[int, int], str]: """返回 {(row, col): value} 字典,行列从 0 开始""" def close(self) ``` **内部结构**: ``` XLSReader ├── OLE2Parser → 解析复合文档,定位 Workbook 流 ├── BIFF8Parser → 解析 BIFF8 记录流 │ ├── SSTParser → 共享字符串表 │ └── CellParser → 单元格记录 └── CellMap → 组装为 (row, col) → value 映射 ``` #### 模块2b:`xlsx_reader` — XLSX 解析引擎 ```python class XLSXReader: def __init__(self, filepath: str) def read_all_cells(self) -> dict[tuple[int, int], str]: """返回 {(row, col): value} 字典,行列从 0 开始""" def close(self) ``` **内部结构**: ``` XLSXReader ├── ZipExtractor → 解压 .xlsx 到内存 ├── SharedStrings → 解析 sharedStrings.xml ├── SheetParser → 解析 sheet1.xml │ ├── CoordParser → 列字母转索引 (A→0, B→1, ...) │ └── CellParser → 提取单元格值 └── CellMap → 组装为 (row, col) → value 映射 ``` #### 模块3:`pinmap_parser` — PinMAP 结构解析 ```python def parse_pinmap(cells: dict[tuple[int, int], str]) -> PinMAP: """ 解析步骤: 1. 排除 (0,0) 后扫描非空单元格,确定方形边界 2. 提取 A1 封装信息 3. 沿四条边提取引脚序号(边界单元格)和 PinName(相邻内侧单元格) 4. 逆时针遍历(左→下→右→上),按单元格位置去重(角点共享) 5. 返回 PinMAP 对象 """ ``` **解析算法**: ``` Step 1: 确定方形边界 - 排除 (0,0)(封装信息单元格) - 扫描所有非空单元格,找到最小/最大行号和列号 - width = max_col - min_col + 1 - height = max_row - min_row + 1 - 验证:width >= 2 且 height >= 2 Step 2: 提取 A1 封装信息 - cells[(0, 0)] → package_info Step 3: 构建 PinName 查找表 每条边的 PinName 位于序号单元格的"内侧相邻"位置: 左边:序号在 (r, min_col), Name 在 (r, min_col+1) 下边:序号在 (max_row, c), Name 在 (max_row-1, c) 右边:序号在 (r, max_col), Name 在 (r, max_col-1) 上边:序号在 (min_row, c), Name 在 (min_row+1, c) Step 4: 逆时针遍历四条边(按单元格位置去重) 4a. 左边:从上到下 (row: min_row → max_row, col: min_col) 4b. 下边:从左到右 (row: max_row, col: min_col+1 → max_col) 4c. 右边:从下到上 (row: max_row-1 → min_row, col: max_col) 4d. 上边:从右到左 (row: min_row, col: max_col-1 → min_col) 角点去重:按 (row, col) 单元格位置去重,而非按 Pin 序号。 这样如果两个不同单元格恰好有相同序号,validator 能检测到。 Step 5: 组装 Pin 列表 按逆时针顺序:Pin1(左上角) → Pin2 → ... → PinN ``` #### 模块4:`validator` — 数据验证 ```python def validate_pinmap(pinmap: PinMAP) -> ValidationResult: """ 验证项: 1. Pin序号唯一性(无重复) 2. Pin序号连续性(1..N 无间隔) 3. PinName 缺失检测(warning,默认 NC) 4. 方形结构完整性(width/height >= 2) """ ``` #### 模块5:`pinlist_generator` — PinList 生成 ```python class PinListGenerator: def __init__(self, pinmap: PinMAP, validation: ValidationResult) def generate(self) -> PinList: """ 生成规则: - A1 = 封装信息 - A列 = PinName - B列 = Pin序号 - 按 Pin序号 递增排序 """ ``` #### 模块6:`xlsx_writer` — XLSX 输出引擎 ```python class XLSXWriter: def __init__(self) def write_pinlist(self, pinlist: PinList, output_path: str) ``` ### 3.2 模块依赖关系 ``` main.py ├── file_selector.py ├── xls_reader.py ──┐ ├── xlsx_reader.py ─┤ │ ▼ │ pinmap_parser.py │ ▼ │ validator.py │ ▼ │ pinlist_generator.py │ ▼ └─────────── xlsx_writer.py ``` --- ## 4. 数据结构设计 ### 4.1 Pin(引脚) ```python @dataclass class Pin: number: int # 引脚序号(1-based) name: str # 引脚名称(缺失时默认为 "NC") edge: str # 所在边: "top" | "right" | "bottom" | "left" position_on_edge: int # 在该边上的位置(0-based) ``` ### 4.2 PinMAP(引脚映射图) ```python @dataclass class PinMAP: package_info: str # A1 单元格封装信息 pins: list[Pin] # 所有引脚(按序号排序) width: int # 方形宽度(列数) height: int # 方形高度(行数) grid_origin: tuple[int, int] # (row, col) 方形左上角 raw_cells: dict[tuple[int, int], str] # 原始单元格数据(调试用) ``` ### 4.3 PinList(引脚列表) ```python @dataclass class PinList: package_info: str # 输出 A1 单元格 rows: list[tuple[str, int]] # [(PinName, Pin序号), ...] 按序号排序 ``` ### 4.4 ValidationResult(验证结果) ```python @dataclass class ValidationError: level: str # "error" | "warning" message: str # 错误描述 details: str # 详细信息(如重复的序号、缺失的Pin等) @dataclass class ValidationResult: is_valid: bool errors: list[ValidationError] warnings: list[ValidationError] ``` ### 4.5 内部:单元格坐标体系 ``` 统一使用 (row, col) 元组,0-based: - row 0 = Excel 第1行 - col 0 = Excel A列 - A1 = (0, 0) - A2 = (1, 0) - C2 = (1, 2) - B4 = (3, 1) ``` --- ## 5. 异常处理策略 ### 5.1 异常分类 | 级别 | 类型 | 处理方式 | 示例 | |------|------|---------|------| | FATAL | 文件格式错误 | 终止 + 错误信息 | 非Excel文件、BIFF损坏 | | FATAL | 结构错误 | 终止 + 错误信息 | 非方形、缺少A1、无边数据 | | ERROR | 数据错误 | 终止 + 详细错误 | 序号不连续、序号重复 | | WARN | 数据警告 | 提示 + 继续 | PinName缺失(默认NC) | | INFO | 信息提示 | 仅显示 | 转换完成、统计信息 | ### 5.2 自定义异常层次 ```python class PinMapError(Exception): """基类异常""" class FileFormatError(PinMapError): """文件格式错误(非xls/xlsx、文件损坏)""" class StructureError(PinMapError): """PinMAP结构错误(非方形、缺少必要数据)""" class ValidationError(PinMapError): """数据验证错误(序号不连续、重复)""" class WarningLevel(PinMapError): """警告级别(PinName缺失等,可继续处理)""" ``` ### 5.3 错误信息规范 ``` [级别] 错误类别: 具体描述 详细信息: ... 建议操作: ... ``` 示例: ``` [ERROR] 序号不连续: 检测到序号间断 预期: 1,2,3,4,5,6 实际: 1,2,3,5,6 缺失序号: 4 建议: 检查PinMAP文件中是否有遗漏的引脚 [WARN] PinName缺失: 检测到 3 个引脚缺少PinName 缺失引脚: Pin 7, Pin 12, Pin 18 处理: 已自动设为 "NC" ``` ### 5.4 主流程异常处理 ```python def main(): try: filepath = select_file() if not filepath: return # 用户取消 cells = read_excel(filepath) pinmap = parse_pinmap(cells) result = validate(pinmap) if result.has_errors(): print_errors(result.errors) return if result.has_warnings(): print_warnings(result.warnings) if not confirm_continue(): return pinlist = generate(pinmap, result) output_path = build_output_path(filepath) write_xlsx(pinlist, output_path) print_success(output_path) except FileFormatError as e: print_fatal(f"文件格式错误: {e}") except StructureError as e: print_fatal(f"结构错误: {e}") except ValidationError as e: print_fatal(f"数据验证失败: {e}") except Exception as e: print_fatal(f"未知错误: {e}") ``` --- ## 6. 文件处理流程图 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 主流程 (main.py) │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌───────────────────────────┐ │ 1. 文件选择 (file_selector) │ │ - tkinter 文件对话框 │ │ - 过滤 *.xls, *.xlsx │ └───────────┬───────────────┘ │ ┌───────────▼───────────────┐ │ 2. 读取 Excel 文件 │ │ ┌─────────────────────┐ │ │ │ 判断文件格式 │ │ │ │ .xls → xls_reader │ │ │ │ .xlsx → xlsx_reader│ │ │ └─────────┬───────────┘ │ │ ┌─────────▼───────────┐ │ │ │ 解析为单元格字典 │ │ │ │ {(row,col): value} │ │ │ └─────────┬───────────┘ │ └────────────┬──────────────┘ │ ┌────────────▼──────────────┐ │ 3. PinMAP 解析 (pinmap_parser) │ │ ┌─────────────────────┐ │ │ │ ① 定位方形边界 │ │ │ │ 扫描非空单元格 │ │ │ │ 确定 width/height│ │ │ └─────────┬───────────┘ │ │ ┌─────────▼───────────┐ │ │ │ ② 提取 A1 封装信息 │ │ │ └─────────┬───────────┘ │ │ ┌─────────▼───────────┐ │ │ │ ③ 沿四边提取引脚 │ │ │ │ 上边 → 右边 │ │ │ │ 下边 → 左边 │ │ │ │ 逆时针排序 │ │ │ └─────────┬───────────┘ │ │ ┌─────────▼───────────┐ │ │ │ ④ 组装 PinMAP 对象 │ │ │ └─────────┬───────────┘ │ └────────────┬──────────────┘ │ ┌────────────▼──────────────┐ │ 4. 数据验证 (validator) │ │ ┌─────────────────────┐ │ │ │ ✓ 序号连续性检查 │ │ │ │ ✓ 序号唯一性检查 │ │ │ │ ✓ PinName 缺失检查 │ │ │ │ ✓ 方形结构完整性 │ │ │ └─────────┬───────────┘ │ │ ┌─────────▼───────────┐ │ │ │ ERROR → 终止流程 │ │ │ │ WARN → 提示确认 │ │ │ └─────────┬───────────┘ │ └────────────┬──────────────┘ │ ┌────────────▼──────────────┐ │ 5. PinList 生成 (generator) │ │ ┌─────────────────────┐ │ │ │ A1 = 封装信息 │ │ │ │ A列 = PinName │ │ │ │ B列 = Pin序号 │ │ │ │ 按序号递增排序 │ │ │ └─────────┬───────────┘ │ └────────────┬──────────────┘ │ ┌────────────▼──────────────┐ │ 6. XLSX 输出 (xlsx_writer) │ │ ┌─────────────────────┐ │ │ │ 构建 OOXML 结构 │ │ │ │ [Content_Types].xml │ │ │ │ xl/workbook.xml │ │ │ │ xl/sharedStrings.xml│ │ │ │ xl/worksheets/ │ │ │ │ sheet1.xml │ │ │ └─────────┬───────────┘ │ │ ┌─────────▼───────────┐ │ │ │ ZIP 打包输出 │ │ │ └─────────┬───────────┘ │ └────────────┬──────────────┘ │ ▼ ┌───────────────────────────┐ │ 完成!输出 .xlsx 文件 │ │ 默认命名: {原文件名}_PinList.xlsx │ └───────────────────────────┘ ``` --- ## 7. PinMAP 结构详解 ### 7.1 坐标映射 以 4×4 方形为例(width=4, height=4): ``` col A(0) col B(1) col C(2) col D(3) row 0 [A1=封装] [PinName] [PinName] [PinName] ← 上边PinName行 row 1 [1] [2] [3] [4] ← 上边Pin序号行 row 2 [PinName] [ ] [PinName] ← 中间区域(留空) row 3 [PinName] [ ] [PinName] ← 中间区域(留空) row 4 [13] [12] [11] [10] ← 下边Pin序号行 [PinName] [PinName] [PinName] [PinName] ← 下边PinName行(行5) ↑ ↑ ↑ ↑ 左边 左边 右边 右边 PinName PinName PinName PinName (列前) (列前) (列后) (列后) ``` **实际引脚分布**: - 上边:Pin 1(A,row1) → Pin 2(B,row1) → Pin 3(C,row1) → Pin 4(D,row1) - 右边:Pin 5(D,row2) → Pin 6(D,row3) → Pin 7(D,row4) - 下边:Pin 8(D,row4) ... 等等 等等,让我重新理清。根据需求描述: ``` C2 是上边最后一个Pin序号,C3是对应PinName A4 是左边第一个Pin序号,B4是对应PinName ``` 这说明: - 行1(Excel第2行)= 上边Pin序号行 - 行2(Excel第3行)= 上边PinName行 - 行3(Excel第4行)= 左边第一个Pin序号行 所以方形区域从 row=1 开始(Excel第2行),row=0 是PinName行。 ### 7.2 四边提取规则(修正版) 设方形区域:行范围 [r_top, r_bottom],列范围 [c_left, c_right] ``` 上边 (Top Edge): Pin序号位置:row=r_top, col=c_left → c_right(从左到右) PinName位置:row=r_top-1, col=c_left → c_right 右边 (Right Edge): Pin序号位置:col=c_right, row=r_top → r_bottom(从上到下) PinName位置:col=c_right+1, row=r_top → r_bottom 下边 (Bottom Edge): Pin序号位置:row=r_bottom, col=c_right → c_left(从右到左) PinName位置:row=r_bottom+1, col=c_right → c_left 左边 (Left Edge): Pin序号位置:col=c_left, row=r_bottom → r_top(从下到上) PinName位置:col=c_left-1, row=r_bottom → r_top(即B列,当c_left=0时) ``` ### 7.3 角点共享规则 ``` 左上角 (c_left, r_top) = 上边起点 = 左边终点 → Pin 1 右上角 (c_right, r_top) = 上边终点 = 右边起点 右下角 (c_right, r_bottom) = 右边终点 = 下边起点 左下角 (c_left, r_bottom) = 下边终点 = 左边终点 总Pin数 = 2 × width + 2 × height - 4 ``` ### 7.4 长方形支持 ``` 非正方形示例:width=6, height=4 总Pin数 = 2×6 + 2×4 - 4 = 16 上边:6个引脚(1-6) 右边:3个引脚(7-9) 下边:5个引脚(10-14) 左边:3个引脚(15-16,回到Pin 1) 验证:6 + 3 + 5 + 2 = 16 ✓(左边排除两个角点) ``` --- ## 8. 任务拆分建议 ### 8.1 推荐拆分方案 建议拆分为 **3 个子任务**,由 2-3 个编码 Agent 并行开发: #### 任务 A:Excel 读写引擎(最复杂,优先开发) **负责模块**:`xls_reader.py`, `xlsx_reader.py`, `xlsx_writer.py` **工作内容**: 1. 实现 BIFF8 OLE2 解析器(xls 读取) 2. 实现 ZIP+XML 解析器(xlsx 读取) 3. 实现 OOXML 生成器(xlsx 写入) 4. 统一接口:`read_excel(filepath) → dict[(row,col), str]` 5. 编写单元测试(用已知 xls/xlsx 文件验证) **预估工作量**:高(BIFF8 解析是最大难点) **关键风险**: - BIFF8 变体多(BIFF5/BIFF8 混用、不同 Unicode 编码) - 需要大量测试文件验证 #### 任务 B:PinMAP 解析与验证(核心业务逻辑) **负责模块**:`pinmap_parser.py`, `validator.py` **工作内容**: 1. 实现方形边界检测算法 2. 实现四边引脚提取逻辑 3. 实现角点共享处理 4. 实现验证规则(连续性、唯一性、完整性) 5. 编写单元测试(模拟各种 PinMAP 布局) **预估工作量**:中 **关键风险**: - 边界条件处理(长方形 vs 正方形、最小尺寸) - 角点共享逻辑的正确性 #### 任务 C:流程编排与输出(集成层) **负责模块**:`main.py`, `file_selector.py`, `pinlist_generator.py` **工作内容**: 1. 实现文件选择对话框 2. 实现 PinList 数据转换 3. 实现输出文件命名和保存 4. 实现主流程异常处理和用户提示 5. 端到端集成测试 **预估工作量**:低 **关键风险**: - tkinter 在 Windows 上的兼容性 - 用户交互流程的友好性 ### 8.2 开发顺序 ``` 第1轮:任务 A(Excel 读写引擎) ↓ 完成后 第2轮:任务 B(PinMAP 解析与验证) ↓ 完成后 第3轮:任务 C(流程编排与输出) ↓ 完成后 集成测试 → 发布 ``` ### 8.3 接口契约(模块间约定) ```python # xls_reader / xlsx_reader 统一接口 def read_excel_cells(filepath: str) -> dict[tuple[int, int], str]: """ 输入: Excel 文件路径 输出: {(row, col): str} 单元格字典 约定: row/col 从 0 开始,所有值转为 str """ # pinmap_parser 接口 def parse_pinmap(cells: dict[tuple[int, int], str]) -> PinMAP: """ 输入: 单元格字典 输出: PinMAP 对象 约定: 结构错误时抛出 StructureError """ # validator 接口 def validate_pinmap(pinmap: PinMAP) -> ValidationResult: """ 输入: PinMAP 对象 输出: ValidationResult 约定: 不抛出异常,所有问题记录在 ValidationResult 中 """ # pinlist_generator 接口 def generate_pinlist(pinmap: PinMAP, validation: ValidationResult) -> PinList: """ 输入: PinMAP + ValidationResult 输出: PinList 对象 约定: 自动处理 WARN 级别的缺失 PinName(设为 NC) """ # xlsx_writer 接口 def write_pinlist_xlsx(pinlist: PinList, output_path: str): """ 输入: PinList + 输出路径 输出: 无(写入文件) 约定: 自动创建父目录 """ ``` --- ## 9. 项目目录结构 ``` pinmap-to-pinlist/ ├── Code/ │ ├── src/ │ │ ├── __init__.py │ │ ├── main.py # 入口点 │ │ ├── file_selector.py # 文件选择 │ │ ├── xls_reader.py # XLS 读取引擎 │ │ ├── xlsx_reader.py # XLSX 读取引擎 │ │ ├── pinmap_parser.py # PinMAP 解析 │ │ ├── validator.py # 数据验证 │ │ ├── pinlist_generator.py # PinList 生成 │ │ ├── xlsx_writer.py # XLSX 写入引擎 │ │ └── models.py # 数据模型定义 │ └── docs/ │ └── architecture-design.md # 本文档 ├── Test/ │ ├── fixtures/ # 测试用 Excel 文件 │ │ ├── sample_4x4.xls │ │ ├── sample_4x4.xlsx │ │ ├── sample_rect.xls │ │ └── ... │ └── test_*.py # 单元测试 └── Releases/ └── pinmap2pinlist.exe # 打包后的可执行文件 ``` --- ## 10. 风险与缓解 | 风险 | 影响 | 概率 | 缓解措施 | |------|------|------|---------| | BIFF8 格式变体导致解析失败 | 高 | 中 | 收集多种 xls 样本测试;优先实现 BIFF8 最常见子集 | | tkinter 在无头环境不可用 | 中 | 低 | 回退到命令行参数模式 | | xlsx 写入的 XML 结构不兼容老版本 Excel | 中 | 低 | 遵循 OOXML 标准,使用最小兼容集 | | 超大文件(>1000引脚)性能问题 | 低 | 低 | 当前场景引脚数通常 <100,无需优化 | --- ## 11. 附录 ### A. BIFF8 记录类型速查 | 记录码 | 名称 | 说明 | |--------|------|------| | 0x0009 | BOF | 块起始 | | 0x000A | EOF | 文件结束 | | 0x00FD | LABELSST | 共享字符串表引用单元格 | | 0x0203 | NUMBER | 浮点数单元格 | | 0x0006 | FORMULA | 公式单元格 | | 0x000C | RK | RK 数值 | | 0x00FC | STRING | 公式字符串结果 | | 0x0034 | SST | 全局共享字符串表 | | 0x0042 | BOUNDSHEET | 工作表信息 | | 0x00E0 | EXTSST | 扩展共享字符串表 | ### B. OOXML xlsx 目录结构 ``` example.xlsx (ZIP) ├── [Content_Types].xml ├── _rels/ │ └── .rels ├── xl/ │ ├── workbook.xml │ ├── _rels/ │ │ └── workbook.xml.rels │ ├── sharedStrings.xml │ ├── styles.xml │ └── worksheets/ │ ├── sheet1.xml │ └── sheet2.xml └── docProps/ ├── core.xml └── app.xml ``` ### C. 列字母 ↔ 索引转换 ```python def col_letter_to_index(letter: str) -> int: """A→0, B→1, ..., Z→25, AA→26, AB→27, ...""" result = 0 for ch in letter.upper(): result = result * 26 + (ord(ch) - ord('A') + 1) return result - 1 def col_index_to_letter(index: int) -> str: """0→A, 1→B, ..., 25→Z, 26→AA, ...""" result = "" index += 1 while index > 0: index -= 1 result = chr(index % 26 + ord('A')) + result index //= 26 return result ``` --- *文档结束 — 请审批后进入编码阶段*