feat: PinMAP转PinList v1.2.0 - 新增PinList转PinMAP反向转换功能
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# 快速入门指南
|
||||
|
||||
本文档帮助你快速上手 PinMAP → PinList 转换器。
|
||||
本文档帮助你快速上手 PinMAP ↔ PinList 双向转换器。
|
||||
|
||||
---
|
||||
|
||||
@@ -46,36 +46,57 @@ cd pinmap-to-pinlist/Code/src/
|
||||
|
||||
### 第二步:运行转换
|
||||
|
||||
#### 方式一:GUI 模式(推荐)
|
||||
#### 方式一:交互式模式(推荐)
|
||||
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
弹出文件选择对话框,选择 `.xls` 或 `.xlsx` 文件即可。
|
||||
运行后显示方向选择菜单,选择 1 或 2:
|
||||
|
||||
```
|
||||
请选择转换方向:
|
||||
1 — PinMAP → PinList
|
||||
2 — PinList → PinMAP
|
||||
|
||||
请输入选项 (1/2): _
|
||||
```
|
||||
|
||||
#### 方式二:命令行模式
|
||||
|
||||
```bash
|
||||
python main.py /path/to/your/input.xlsx
|
||||
# PinMAP → PinList(直接指定文件)
|
||||
python main.py /path/to/your/PinMAP.xlsx
|
||||
|
||||
# PinList → PinMAP(命令行模式默认走 MAP→List 方向)
|
||||
# 如需 List→MAP,请使用交互式模式
|
||||
```
|
||||
|
||||
### 第三步:查看输出
|
||||
|
||||
转换完成后,在当前目录生成 `{原文件名}_PinList.xlsx`:
|
||||
转换完成后,在当前目录生成输出文件:
|
||||
|
||||
```
|
||||
输入: QFP44_PinMAP.xlsx
|
||||
输出: QFP44_PinMAP_PinList.xlsx
|
||||
PinMAP → PinList: QFP44_PinMAP.xlsx → QFP44_PinMAP_PinList.xlsx
|
||||
PinList → PinMAP: QFN20_PinList.xlsx → QFN20_PinList_PinMAP.xlsx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 使用示例
|
||||
## 方向一:PinMAP → PinList
|
||||
|
||||
### 示例 1:标准方形 PinMAP
|
||||
将方形封装引脚布局图转换为线性引脚列表。
|
||||
|
||||
**输入文件** `QFP44.xlsx`:
|
||||
### 操作步骤
|
||||
|
||||
1. 运行 `python main.py`,选择方向 **1**
|
||||
2. 选择 PinMAP 文件(`.xls` 或 `.xlsx`)
|
||||
3. 等待转换完成
|
||||
4. 查看输出的 `_PinList.xlsx` 文件
|
||||
|
||||
### 使用示例
|
||||
|
||||
**输入文件** `QFP44.xlsx`(6×6 方形封装,8 个引脚):
|
||||
|
||||
```
|
||||
A B C D E F
|
||||
@@ -88,7 +109,7 @@ python main.py /path/to/your/input.xlsx
|
||||
7 3 4
|
||||
```
|
||||
|
||||
**运行命令**:
|
||||
**运行**:
|
||||
|
||||
```bash
|
||||
python main.py QFP44.xlsx
|
||||
@@ -97,12 +118,20 @@ python main.py QFP44.xlsx
|
||||
**输出**:
|
||||
|
||||
```
|
||||
[INFO] 正在读取文件: QFP44.xlsx
|
||||
[INFO] 文件读取完成,共 16 个非空单元格
|
||||
[INFO] 正在解析 PinMAP 结构...
|
||||
[INFO] 解析完成: 6x6 方形,共 8 个Pin
|
||||
[INFO] 封装信息: QFP-44
|
||||
[INFO] 正在验证数据...
|
||||
[INFO] 验证通过
|
||||
[INFO] 正在生成 PinList...
|
||||
[INFO] 正在写入输出文件: QFP44_PinList.xlsx
|
||||
|
||||
[SUCCESS] 转换完成!输出文件: QFP44_PinList.xlsx
|
||||
- 封装信息: QFP-44
|
||||
- Pin数量: 8
|
||||
[SUCCESS] 转换完成!
|
||||
输出文件: QFP44_PinList.xlsx
|
||||
封装信息: QFP-44
|
||||
Pin数量: 8
|
||||
```
|
||||
|
||||
**输出文件内容**:
|
||||
@@ -118,62 +147,7 @@ python main.py QFP44.xlsx
|
||||
7 Pin6 6
|
||||
```
|
||||
|
||||
### 示例 2:长方形 PinMAP
|
||||
|
||||
**输入文件** `LQFP100.xlsx`(13 个引脚的长方形封装)
|
||||
|
||||
```bash
|
||||
python main.py LQFP100.xlsx
|
||||
```
|
||||
|
||||
**输出**:
|
||||
|
||||
```
|
||||
[INFO] 解析完成: 长方形结构,共 13 个Pin
|
||||
[INFO] 封装信息: LQFP-100
|
||||
|
||||
[SUCCESS] 转换完成!输出文件: LQFP100_PinList.xlsx
|
||||
- 封装信息: LQFP-100
|
||||
- Pin数量: 13
|
||||
```
|
||||
|
||||
### 示例 3:处理警告
|
||||
|
||||
当 PinMAP 中部分引脚缺少 PinName 时:
|
||||
|
||||
```
|
||||
[INFO] 解析完成: 6x6 方形,共 8 个Pin
|
||||
[INFO] 封装信息: QFP-44
|
||||
|
||||
[WARN] 发现 3 个警告:
|
||||
- 检测到 3 个引脚缺少 PinName: 缺失引脚序号: [2, 3, 4],将默认为 NC
|
||||
|
||||
[SUCCESS] 转换完成!输出文件: QFP44_PinList.xlsx
|
||||
- 封装信息: QFP-44
|
||||
- Pin数量: 8
|
||||
```
|
||||
|
||||
缺失 PinName 的引脚在输出中自动标记为 "NC"。
|
||||
|
||||
### 示例 4:处理错误
|
||||
|
||||
当 PinMAP 存在数据错误时:
|
||||
|
||||
```
|
||||
[INFO] 解析完成: 6x6 方形,共 8 个Pin
|
||||
[INFO] 封装信息: QFP-44
|
||||
|
||||
[ERROR] 发现 1 个错误:
|
||||
- Pin序号不连续: 缺失的序号: [3]
|
||||
|
||||
转换终止,请修正PinMAP文件后重试。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PinMAP 文件规范
|
||||
|
||||
### 格式要求
|
||||
### PinMAP 文件规范
|
||||
|
||||
| 要求 | 说明 |
|
||||
|------|------|
|
||||
@@ -192,7 +166,204 @@ python main.py LQFP100.xlsx
|
||||
上边:序号在 (min_row, c),PinName 在 (min_row+1, c)
|
||||
```
|
||||
|
||||
### 支持的输入格式
|
||||
---
|
||||
|
||||
## 方向二:PinList → PinMAP
|
||||
|
||||
将线性引脚列表转换为方形封装引脚布局图。
|
||||
|
||||
### 操作步骤
|
||||
|
||||
1. 运行 `python main.py`,选择方向 **2**
|
||||
2. 选择 PinList 文件(`.xls` 或 `.xlsx`)
|
||||
3. **输入 PinMAP 行数**(至少 2)
|
||||
4. **输入 PinMAP 列数**(至少 2)
|
||||
5. 等待转换完成
|
||||
6. 查看输出的 `_PinMAP.xlsx` 文件
|
||||
|
||||
### 尺寸输入说明
|
||||
|
||||
PinMAP 的引脚分布在四条边上,总引脚数由网格尺寸决定:
|
||||
|
||||
```
|
||||
总引脚数 = 2 × 行数 + 2 × 列数 − 4
|
||||
```
|
||||
|
||||
常见封装尺寸参考:
|
||||
|
||||
| 封装类型 | 引脚数 | 推荐行数 | 推荐列数 |
|
||||
|----------|--------|----------|----------|
|
||||
| QFP-8 | 8 | 4 | 4 |
|
||||
| QFP-16 | 16 | 6 | 6 |
|
||||
| QFP-20 | 20 | 6 | 6 |
|
||||
| QFP-24 | 24 | 8 | 6 |
|
||||
| QFP-32 | 32 | 10 | 8 |
|
||||
| QFP-44 | 44 | 12 | 10 |
|
||||
| QFP-64 | 64 | 16 | 16 |
|
||||
| QFP-100 | 100 | 26 | 26 |
|
||||
|
||||
> **提示**:如果不确定尺寸,可以先用公式反推:`行数 + 列数 = (引脚数 + 4) / 2`,然后根据需要调整行和列的比例。
|
||||
|
||||
### 模板文件说明
|
||||
|
||||
PinList → PinMAP 转换时,程序会自动尝试从输入文件所在目录读取模板样式:
|
||||
|
||||
- **模板来源**:程序会尝试解析与输入文件同名的 `.xlsx` 模板文件中的样式信息
|
||||
- **提取内容**:字体(名称、大小、粗体、斜体、颜色)、填充、边框、列宽、行高
|
||||
- **优雅降级**:如果模板不存在或解析失败,程序会自动使用默认样式,不影响转换流程
|
||||
|
||||
### 使用示例
|
||||
|
||||
**输入文件** `QFN20_PinList.xlsx`(20 个引脚):
|
||||
|
||||
```
|
||||
A B
|
||||
1 QFN-20
|
||||
2 VCC 1
|
||||
3 GND 2
|
||||
4 IO0 3
|
||||
5 IO1 4
|
||||
6 IO2 5
|
||||
7 IO3 6
|
||||
8 IO4 7
|
||||
9 IO5 8
|
||||
10 IO6 9
|
||||
11 IO7 10
|
||||
12 NC 11
|
||||
13 NC 12
|
||||
14 NC 13
|
||||
15 NC 14
|
||||
16 NC 15
|
||||
17 NC 16
|
||||
18 NC 17
|
||||
19 NC 18
|
||||
20 NC 19
|
||||
21 NC 20
|
||||
```
|
||||
|
||||
**运行**:
|
||||
|
||||
```bash
|
||||
python main.py
|
||||
# 选择方向: 2 (PinList → PinMAP)
|
||||
# 选择文件: QFN20_PinList.xlsx
|
||||
# 输入行数: 6
|
||||
# 输入列数: 6
|
||||
```
|
||||
|
||||
**输出**:
|
||||
|
||||
```
|
||||
[INFO] PinMAP 尺寸: 6 行 × 6 列
|
||||
[INFO] 正在解析 PinList 文件: QFN20_PinList.xlsx
|
||||
[INFO] 解析完成: 封装信息 'QFN-20', 共 20 个引脚
|
||||
[INFO] 正在验证数据...
|
||||
[INFO] 验证通过
|
||||
[INFO] 正在生成 PinMAP 并写入: QFN20_PinList_PinMAP.xlsx
|
||||
|
||||
[SUCCESS] 转换完成!
|
||||
输出文件: QFN20_PinList_PinMAP.xlsx
|
||||
封装信息: QFN-20
|
||||
PinMAP 尺寸: 6×6
|
||||
Pin数量: 20
|
||||
```
|
||||
|
||||
**输出文件内容**(6×6 网格,20 个引脚):
|
||||
|
||||
```
|
||||
A B C D E F
|
||||
1 QFN-20 IO8 IO7
|
||||
2 1 VCC IO6 IO5
|
||||
3 2 GND IO4 IO3
|
||||
4 3 IO0 IO2 IO1
|
||||
5 4 IO1 NC NC
|
||||
6 20 19 18 17 16
|
||||
```
|
||||
|
||||
### 布局规则
|
||||
|
||||
引脚按**逆时针**分配到四条边(左上角为 1 脚):
|
||||
|
||||
```
|
||||
左边: 从上到下(rows 个引脚)
|
||||
下边: 从左到右(cols − 1 个引脚)
|
||||
右边: 从下到上(rows − 2 个引脚)
|
||||
上边: 从右到左(cols − 1 个引脚)
|
||||
```
|
||||
|
||||
PinName 与序号的相对位置:
|
||||
|
||||
```
|
||||
左边:Name 在序号右侧
|
||||
下边:Name 在序号上方
|
||||
右边:Name 在序号左侧
|
||||
上边:Name 在序号下方
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 使用示例汇总
|
||||
|
||||
### 示例 1:标准方形 PinMAP(MAP→List)
|
||||
|
||||
**输入** `QFP44.xlsx`(6×6,8 Pin)
|
||||
|
||||
```bash
|
||||
python main.py QFP44.xlsx
|
||||
```
|
||||
|
||||
**输出** `QFP44_PinList.xlsx`(A 列 PinName,B 列序号)
|
||||
|
||||
### 示例 2:长方形 PinMAP(MAP→List)
|
||||
|
||||
**输入** `LQFP100.xlsx`(长方形,13 Pin)
|
||||
|
||||
```bash
|
||||
python main.py LQFP100.xlsx
|
||||
```
|
||||
|
||||
**输出** `LQFP100_PinList.xlsx`
|
||||
|
||||
### 示例 3:标准 PinList(List→MAP)
|
||||
|
||||
**输入** `QFN20_PinList.xlsx`(20 Pin)
|
||||
|
||||
```bash
|
||||
python main.py
|
||||
# 选择 2,输入 6×6
|
||||
```
|
||||
|
||||
**输出** `QFN20_PinList_PinMAP.xlsx`(6×6 方形)
|
||||
|
||||
### 示例 4:处理警告
|
||||
|
||||
当 PinMAP 中部分引脚缺少 PinName 时:
|
||||
|
||||
```
|
||||
[WARN] 发现 3 个警告:
|
||||
- 检测到 3 个引脚缺少 PinName: 缺失引脚序号: [2, 3, 4],将默认为 NC
|
||||
|
||||
[SUCCESS] 转换完成!
|
||||
```
|
||||
|
||||
缺失 PinName 的引脚在输出中自动标记为 "NC"。
|
||||
|
||||
### 示例 5:处理错误
|
||||
|
||||
当 PinList 引脚数与网格尺寸不匹配时:
|
||||
|
||||
```
|
||||
[ERROR] 验证未通过,发现 1 个错误:
|
||||
- Pin数量与网格周长不匹配: 网格 6×6 需要 20 个引脚,但 PinList 有 24 个
|
||||
|
||||
转换终止,请修正PinList文件或网格尺寸后重试。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 支持的格式
|
||||
|
||||
### 输入格式
|
||||
|
||||
| 格式 | 扩展名 | 支持情况 |
|
||||
|------|--------|----------|
|
||||
@@ -233,7 +404,7 @@ python main.py input.xlsx
|
||||
|
||||
### Q3: 提示 "A1 单元格为空,缺少封装信息"
|
||||
|
||||
**原因**:PinMAP 文件的 A1 单元格为空。
|
||||
**原因**:文件的 A1 单元格为空。
|
||||
|
||||
**解决**:在 Excel 中打开文件,在 A1 单元格填入封装信息(如 "QFP-44"),保存后重新转换。
|
||||
|
||||
@@ -241,21 +412,29 @@ python main.py input.xlsx
|
||||
|
||||
**原因**:Pin 序号存在间隔(如 1, 2, 4, 5,缺少 3)。
|
||||
|
||||
**解决**:检查 PinMAP 文件,补全缺失的引脚序号。
|
||||
**解决**:检查文件,补全缺失的引脚序号。
|
||||
|
||||
### Q5: 提示 "Pin序号重复"
|
||||
|
||||
**原因**:同一个 Pin 序号出现了多次。
|
||||
|
||||
**解决**:检查 PinMAP 文件,修正重复的序号。
|
||||
**解决**:检查文件,修正重复的序号。
|
||||
|
||||
### Q6: 警告 "检测到 N 个引脚缺少 PinName"
|
||||
### Q6: 提示 "Pin数量与网格周长不匹配"
|
||||
|
||||
**原因**:PinList 的引脚数与输入的 rows×cols 网格周长不一致。
|
||||
|
||||
**解决**:
|
||||
- 检查引脚数量是否正确
|
||||
- 或调整网格尺寸,使 `2×rows + 2×cols − 4 = 引脚数`
|
||||
|
||||
### Q7: 警告 "检测到 N 个引脚缺少 PinName"
|
||||
|
||||
**说明**:这是警告而非错误,转换会继续进行。缺失的 PinName 会自动设为 "NC"。
|
||||
|
||||
**解决**(可选):在 Excel 中补全缺失的 PinName,重新转换。
|
||||
|
||||
### Q7: Linux 下没有弹出文件选择对话框
|
||||
### Q8: Linux 下没有弹出文件选择对话框
|
||||
|
||||
**说明**:Linux 无头环境(无显示器)不支持 tkinter GUI。
|
||||
|
||||
@@ -269,26 +448,31 @@ python main.py /path/to/input.xlsx
|
||||
sudo apt install python3-tk
|
||||
```
|
||||
|
||||
### Q8: 输出文件打不开
|
||||
### Q9: 输出文件打不开
|
||||
|
||||
**可能原因**:Excel 版本过旧(2003 及以下不支持 .xlsx)。
|
||||
|
||||
**解决**:使用 Excel 2007+ 或 WPS Office 打开输出文件。
|
||||
|
||||
### Q9: 支持多大的 PinMAP?
|
||||
### Q10: 支持多大的 PinMAP?
|
||||
|
||||
**回答**:当前实现适合 < 1000 引脚的场景。典型 IC 封装引脚数在 8~200 之间,完全满足需求。
|
||||
|
||||
### Q10: 能否批量转换多个文件?
|
||||
### Q11: 能否批量转换多个文件?
|
||||
|
||||
**回答**:当前版本一次处理一个文件。如需批量转换,可使用 shell 脚本:
|
||||
|
||||
```bash
|
||||
# PinMAP → PinList
|
||||
for f in *.xlsx; do
|
||||
python main.py "$f"
|
||||
done
|
||||
```
|
||||
|
||||
### Q12: 命令行模式下如何执行 PinList → PinMAP?
|
||||
|
||||
**回答**:命令行模式下直接传入文件参数默认走 PinMAP → PinList 方向。如需执行 PinList → PinMAP,请使用交互式模式(不带参数运行),选择方向 2。
|
||||
|
||||
---
|
||||
|
||||
## 测试验证
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
# PinMAP → PinList 转换器
|
||||
# PinMAP ↔ PinList 双向转换器
|
||||
|
||||
将 Excel 格式的 **PinMAP** 文件(方形封装引脚布局图)自动转换为 **PinList** 格式(引脚序号列表),消除手动抄录的低效与错误风险。
|
||||
将 Excel 格式的 **PinMAP**(方形封装引脚布局图)与 **PinList**(引脚序号列表)互相转换,消除手动抄录的低效与错误风险。
|
||||
|
||||
- **PinMAP → PinList**:自动识别方形/长方形结构,逆时针提取引脚,生成线性列表
|
||||
- **PinList → PinMAP**:根据引脚列表和网格尺寸,自动计算布局并生成方形封装图
|
||||
|
||||
---
|
||||
|
||||
## 项目简介
|
||||
|
||||
在 IC 封装设计中,PinMAP 以方形/长方形矩阵形式展示引脚分布,而 PinList 则以线性列表形式提供引脚序号对照。本项目通过纯 Python 实现,自动完成从 PinMAP 到 PinList 的转换,支持 `.xls` 和 `.xlsx` 两种格式。
|
||||
在 IC 封装设计中,PinMAP 以方形/长方形矩阵形式展示引脚分布,而 PinList 则以线性列表形式提供引脚序号对照。本项目通过纯 Python 实现,自动完成 PinMAP 与 PinList 之间的双向转换,支持 `.xls` 和 `.xlsx` 两种格式。
|
||||
|
||||
**版本**: v1.0.0
|
||||
**发布日期**: 2026-05-25
|
||||
**版本**: v1.2.0
|
||||
**发布日期**: 2026-05-28
|
||||
**运行平台**: Windows(tkinter GUI)/ Linux(命令行回退)
|
||||
**技术栈**: Python 标准库,零第三方依赖
|
||||
|
||||
@@ -21,19 +24,30 @@
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| **PinMAP 解析** | 自动识别方形/长方形结构,沿四条边(左→下→右→上)逆时针提取引脚 |
|
||||
| **数据验证** | 检测序号不连续、序号重复、PinName 缺失、A1 封装信息缺失 |
|
||||
| **PinList 生成** | A 列 PinName,B 列 Pin 序号,按序号递增排序 |
|
||||
| **PinMAP → PinList** | 自动识别方形/长方形结构,沿四条边(左→下→右→上)逆时针提取引脚,生成 PinList |
|
||||
| **PinList → PinMAP** | 根据引脚列表和网格尺寸,自动计算布局并生成 PinMAP |
|
||||
| **数据验证** | 双向验证:检测序号不连续、序号重复、PinName 缺失、A1 封装信息缺失、周长匹配 |
|
||||
| **模板样式** | PinList → PinMAP 时自动读取模板文件的字体、填充、边框、列宽、行高等样式 |
|
||||
| **双格式支持** | 同时支持 `.xls`(BIFF8 引擎)和 `.xlsx`(OOXML 引擎) |
|
||||
| **双模式运行** | GUI 文件选择对话框 + 命令行参数模式 |
|
||||
|
||||
### 验证规则
|
||||
|
||||
#### PinMAP → PinList 验证
|
||||
|
||||
- **序号连续性**:Pin 序号必须为 1~N 连续整数,无间隔
|
||||
- **序号唯一性**:每个 Pin 序号只能出现一次,无重复
|
||||
- **PinName 完整性**:缺失 PinName 的引脚自动标记为 "NC"(警告级别,不中断流程)
|
||||
- **结构完整性**:方形区域至少 2×2,A1 单元格必须包含封装信息
|
||||
|
||||
#### PinList → PinMAP 验证
|
||||
|
||||
- **序号连续性**:Pin 序号必须从 1 开始连续无缺失
|
||||
- **序号唯一性**:每个 Pin 序号只能出现一次,无重复
|
||||
- **周长匹配**:Pin 总数 = 2×rows + 2×cols − 4(与网格周长一致)
|
||||
- **PinName 完整性**:缺失 PinName 的引脚自动标记为 "NC"(警告级别)
|
||||
- **非 4 倍数提示**:Pin 数量不是 4 的倍数时提示(信息级别)
|
||||
|
||||
---
|
||||
|
||||
## 技术栈
|
||||
@@ -49,13 +63,22 @@
|
||||
| `xlsx_writer.py` | XLSX 写入引擎(OOXML 构建) | `zipfile`, `xml.etree.ElementTree` |
|
||||
| `file_selector.py` | 文件选择对话框 | `tkinter.filedialog` |
|
||||
| `pinmap_parser.py` | PinMAP 结构解析 | 纯 Python |
|
||||
| `validator.py` | 数据验证 | `collections.Counter` |
|
||||
| `pinmap_layout.py` | PinMAP 布局计算 | 纯 Python |
|
||||
| `pinmap_generator.py` | PinMAP 生成与输出 | 纯 Python |
|
||||
| `pinlist_parser.py` | PinList 文件解析 | 纯 Python |
|
||||
| `pinlist_validator.py` | PinList 数据验证 | `collections.Counter` |
|
||||
| `pinlist_generator.py` | PinList 生成 | 纯 Python |
|
||||
| `validator.py` | PinMAP 数据验证 | `collections.Counter` |
|
||||
| `template_reader.py` | 模板样式提取 | `zipfile`, `xml.etree.ElementTree` |
|
||||
| `models.py` | 数据模型 | `dataclasses` |
|
||||
| `utils.py` | 工具函数 | 纯 Python |
|
||||
|
||||
### 核心技术亮点
|
||||
|
||||
- **BIFF8 手动解析**:从零实现 OLE2 复合文档 + BIFF8 记录流解析,支持 SST、LABELSST、NUMBER、FORMULA、RK、MULRK、LABEL 等记录类型
|
||||
- **OOXML 手动构建**:不使用 openpyxl/xlrd,纯手工构建 `[Content_Types].xml`、`workbook.xml`、`sharedStrings.xml`、`sheet1.xml` 等 OOXML 结构
|
||||
- **布局算法**:根据网格尺寸自动计算四边引脚分配,支持任意 rows×cols 的矩形封装
|
||||
- **模板样式引擎**:从 xlsx 文件中提取字体、填充、边框、列宽、行高等样式并应用到输出文件
|
||||
- **模块化架构**:解析 → 验证 → 生成 → 输出,各模块职责清晰,接口契约明确
|
||||
|
||||
---
|
||||
@@ -68,8 +91,32 @@
|
||||
- Windows 环境(GUI 模式需要 tkinter)
|
||||
- Linux/Mac 环境(仅命令行模式)
|
||||
|
||||
### 交互式模式(推荐)
|
||||
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
运行后显示转换方向选择菜单:
|
||||
|
||||
```
|
||||
============================================================
|
||||
PinMAP ↔ PinList 双向转换器
|
||||
支持 PinMAP→PinList 与 PinList→PinMAP 互转
|
||||
支持.xls和.xlsx格式,输出.xlsx格式
|
||||
============================================================
|
||||
|
||||
请选择转换方向:
|
||||
1 — PinMAP → PinList
|
||||
2 — PinList → PinMAP
|
||||
|
||||
请输入选项 (1/2):
|
||||
```
|
||||
|
||||
### 命令行模式
|
||||
|
||||
#### PinMAP → PinList
|
||||
|
||||
```bash
|
||||
# 基本用法
|
||||
python main.py input.xlsx
|
||||
@@ -80,16 +127,34 @@ python main.py input.xls
|
||||
# 输出文件自动命名为 input_PinList.xlsx
|
||||
```
|
||||
|
||||
#### PinList → PinMAP
|
||||
|
||||
```bash
|
||||
# 命令行模式:需提供文件路径
|
||||
python main.py input_PinList.xlsx
|
||||
|
||||
# 运行后需要手动输入 PinMAP 尺寸:
|
||||
# 请输入 PinMAP 行数: 6
|
||||
# 请输入 PinMAP 列数: 6
|
||||
# 输出文件自动命名为 input_PinList_PinMAP.xlsx
|
||||
```
|
||||
|
||||
> **注意**:命令行模式下直接传入文件参数时,默认走 PinMAP → PinList 方向。如需 PinList → PinMAP,请使用交互式模式(不带参数运行)选择方向 2。
|
||||
|
||||
### GUI 模式
|
||||
|
||||
```bash
|
||||
# 不带参数运行,弹出文件选择对话框
|
||||
# 不带参数运行,弹出方向选择 + 文件选择对话框
|
||||
python main.py
|
||||
```
|
||||
|
||||
在对话框中选择 `.xls` 或 `.xlsx` 文件,点击"打开"即可开始转换。
|
||||
选择方向后,在对话框中选择 `.xls` 或 `.xlsx` 文件,点击"打开"即可开始转换。
|
||||
|
||||
### 输出示例
|
||||
---
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例 1:PinMAP → PinList
|
||||
|
||||
输入 PinMAP(方形封装):
|
||||
|
||||
@@ -104,7 +169,32 @@ python main.py
|
||||
7 3 4
|
||||
```
|
||||
|
||||
输出 PinList:
|
||||
**运行命令**:
|
||||
|
||||
```bash
|
||||
python main.py QFP44.xlsx
|
||||
```
|
||||
|
||||
**输出**:
|
||||
|
||||
```
|
||||
[INFO] 正在读取文件: QFP44.xlsx
|
||||
[INFO] 文件读取完成,共 16 个非空单元格
|
||||
[INFO] 正在解析 PinMAP 结构...
|
||||
[INFO] 解析完成: 6x6 方形,共 8 个Pin
|
||||
[INFO] 封装信息: QFP-44
|
||||
[INFO] 正在验证数据...
|
||||
[INFO] 验证通过
|
||||
[INFO] 正在生成 PinList...
|
||||
[INFO] 正在写入输出文件: QFP44_PinList.xlsx
|
||||
|
||||
[SUCCESS] 转换完成!
|
||||
输出文件: QFP44_PinList.xlsx
|
||||
封装信息: QFP-44
|
||||
Pin数量: 8
|
||||
```
|
||||
|
||||
**输出 PinList**:
|
||||
|
||||
```
|
||||
A B
|
||||
@@ -117,6 +207,88 @@ python main.py
|
||||
7 Pin6 6
|
||||
```
|
||||
|
||||
### 示例 2:PinList → PinMAP
|
||||
|
||||
输入 PinList:
|
||||
|
||||
```
|
||||
A B
|
||||
1 QFN-20
|
||||
2 VCC 1
|
||||
3 GND 2
|
||||
4 IO0 3
|
||||
5 IO1 4
|
||||
6 IO2 5
|
||||
7 IO3 6
|
||||
8 IO4 7
|
||||
9 IO5 8
|
||||
10 IO6 9
|
||||
11 IO7 10
|
||||
12 NC 11
|
||||
13 NC 12
|
||||
14 NC 13
|
||||
15 NC 14
|
||||
16 NC 15
|
||||
17 NC 16
|
||||
18 NC 17
|
||||
19 NC 18
|
||||
20 NC 19
|
||||
21 NC 20
|
||||
```
|
||||
|
||||
**运行命令**:
|
||||
|
||||
```bash
|
||||
python main.py
|
||||
# 选择方向: 2 (PinList → PinMAP)
|
||||
# 选择文件: QFN20_PinList.xlsx
|
||||
# 输入行数: 6
|
||||
# 输入列数: 6
|
||||
```
|
||||
|
||||
**输出**:
|
||||
|
||||
```
|
||||
[INFO] 正在解析 PinList 文件: QFN20_PinList.xlsx
|
||||
[INFO] 解析完成: 封装信息 'QFN-20', 共 20 个引脚
|
||||
[INFO] 正在验证数据...
|
||||
[INFO] 验证通过
|
||||
[INFO] 正在生成 PinMAP 并写入: QFN20_PinList_PinMAP.xlsx
|
||||
|
||||
[SUCCESS] 转换完成!
|
||||
输出文件: QFN20_PinList_PinMAP.xlsx
|
||||
封装信息: QFN-20
|
||||
PinMAP 尺寸: 6×6
|
||||
Pin数量: 20
|
||||
```
|
||||
|
||||
**输出 PinMAP**(6×6 网格,20 个引脚):
|
||||
|
||||
```
|
||||
A B C D E F
|
||||
1 QFN-20 IO8 IO7
|
||||
2 1 VCC IO6 IO5
|
||||
3 2 GND IO4 IO3
|
||||
4 3 IO0 IO2 IO1
|
||||
5 4 IO1 NC NC
|
||||
6 20 19 18 17 16
|
||||
```
|
||||
|
||||
### 示例 3:尺寸不匹配错误
|
||||
|
||||
当 PinList 引脚数与网格周长不匹配时:
|
||||
|
||||
```
|
||||
[ERROR] 验证未通过,发现 1 个错误:
|
||||
- Pin数量与网格周长不匹配: 网格 6×6 需要 20 个引脚,但 PinList 有 24 个
|
||||
|
||||
转换终止,请修正PinList文件或网格尺寸后重试。
|
||||
```
|
||||
|
||||
### 示例 4:使用模板样式
|
||||
|
||||
PinList → PinMAP 转换时,程序会自动尝试从同目录下的模板文件读取样式(字体、边框、列宽等),使输出 PinMAP 的格式与目标模板保持一致。
|
||||
|
||||
---
|
||||
|
||||
## 项目结构
|
||||
@@ -125,14 +297,19 @@ python main.py
|
||||
pinmap-to-pinlist/
|
||||
├── Code/
|
||||
│ ├── src/
|
||||
│ │ ├── main.py # 主入口:流程编排
|
||||
│ │ ├── main.py # 主入口:流程编排 + 双向转换
|
||||
│ │ ├── file_selector.py # 文件选择(GUI + 命令行回退)
|
||||
│ │ ├── xls_reader.py # XLS (BIFF8) 读取引擎
|
||||
│ │ ├── xlsx_reader.py # XLSX 读取引擎
|
||||
│ │ ├── xlsx_writer.py # XLSX 写入引擎
|
||||
│ │ ├── xlsx_writer.py # XLSX 写入引擎(含样式支持)
|
||||
│ │ ├── pinmap_parser.py # PinMAP 结构解析
|
||||
│ │ ├── validator.py # 数据验证
|
||||
│ │ ├── pinlist_generator.py # PinList 生成
|
||||
│ │ ├── pinmap_layout.py # PinMAP 布局计算(List→MAP)
|
||||
│ │ ├── pinmap_generator.py # PinMAP 生成与输出(List→MAP)
|
||||
│ │ ├── pinlist_parser.py # PinList 文件解析(List→MAP)
|
||||
│ │ ├── pinlist_validator.py # PinList 数据验证(List→MAP)
|
||||
│ │ ├── pinlist_generator.py # PinList 生成(MAP→List)
|
||||
│ │ ├── validator.py # PinMAP 数据验证(MAP→List)
|
||||
│ │ ├── template_reader.py # 模板样式提取(List→MAP)
|
||||
│ │ ├── models.py # 数据模型
|
||||
│ │ ├── utils.py # 工具函数
|
||||
│ │ └── test_pinmap.py # 单元测试
|
||||
@@ -192,7 +369,7 @@ pinmap-to-pinlist/
|
||||
|
||||
## 解析算法说明
|
||||
|
||||
### PinMAP 结构
|
||||
### PinMAP → PinList:逆时针提取
|
||||
|
||||
PinMAP 以方形/长方形矩阵展示引脚分布:
|
||||
|
||||
@@ -205,8 +382,6 @@ row 3 [PinName] [ ] [PinName]
|
||||
row 4 [13] [12] [11] [10] ← 下边 Pin 序号
|
||||
```
|
||||
|
||||
### 逆时针提取规则
|
||||
|
||||
引脚沿四条边**逆时针**提取:
|
||||
|
||||
1. **左边**:从上到下
|
||||
@@ -216,23 +391,52 @@ row 4 [13] [12] [11] [10] ← 下边 Pin 序号
|
||||
|
||||
角点单元格只计数一次(按单元格位置去重)。
|
||||
|
||||
### PinList 输出规则
|
||||
### PinList → PinMAP:布局计算
|
||||
|
||||
根据用户输入的 rows × cols 网格尺寸,将引脚列表按**逆时针**分配到四条边:
|
||||
|
||||
```
|
||||
总引脚数 = 2 × rows + 2 × cols − 4
|
||||
|
||||
左边: rows 个引脚(从上到下)
|
||||
下边: cols − 1 个引脚(从左到右)
|
||||
右边: rows − 2 个引脚(从下到上)
|
||||
上边: cols − 1 个引脚(从右到左)
|
||||
```
|
||||
|
||||
PinName 与序号的相对位置:
|
||||
|
||||
```
|
||||
左边:序号在 (r, 0),PinName 在 (r, 1) → Name 在序号右侧
|
||||
下边:序号在 (rows, c),PinName 在 (rows-1, c) → Name 在序号上方
|
||||
右边:序号在 (r, cols),PinName 在 (r, cols-1) → Name 在序号左侧
|
||||
上边:序号在 (1, c),PinName 在 (2, c) → Name 在序号下方
|
||||
```
|
||||
|
||||
### PinList 输出规则(MAP→List)
|
||||
|
||||
- A1 单元格:封装信息(从 PinMAP 的 A1 复制)
|
||||
- A 列:PinName(缺失时自动设为 "NC")
|
||||
- B 列:Pin 序号
|
||||
- 按 Pin 序号递增排序
|
||||
|
||||
### PinMAP 输出规则(List→MAP)
|
||||
|
||||
- A1 单元格:封装信息(从 PinList 的 A1 读取)
|
||||
- 四边分布:序号 + PinName 按布局算法填入网格
|
||||
- 缺失 PinName 自动设为 "NC"
|
||||
- 可选:应用模板样式(字体、边框、列宽、行高)
|
||||
|
||||
---
|
||||
|
||||
## 错误处理
|
||||
|
||||
| 级别 | 类型 | 行为 |
|
||||
|------|------|------|
|
||||
| `[FATAL]` | 文件格式错误 / 结构错误 | 终止处理,显示错误信息 |
|
||||
| `[ERROR]` | 数据验证错误(重复/不连续) | 终止处理,显示详细错误 |
|
||||
| `[FATAL]` | 文件格式错误 / 结构错误 / 布局计算失败 | 终止处理,显示错误信息 |
|
||||
| `[ERROR]` | 数据验证错误(重复/不连续/周长不匹配) | 终止处理,显示详细错误 |
|
||||
| `[WARN]` | PinName 缺失 | 提示警告,自动设为 "NC",继续处理 |
|
||||
| `[INFO]` | 解析进度信息 | 仅显示,不影响流程 |
|
||||
| `[INFO]` | 解析进度信息 / 非 4 倍数提示 | 仅显示,不影响流程 |
|
||||
| `[SUCCESS]` | 转换完成 | 显示输出文件路径和统计信息 |
|
||||
|
||||
---
|
||||
|
||||
@@ -2,6 +2,198 @@
|
||||
|
||||
---
|
||||
|
||||
## v1.2.0 — 2026-05-28
|
||||
|
||||
### ✨ 新增 PinList → PinMAP 反向转换
|
||||
|
||||
v1.2.0 为项目增加了完整的反向转换能力,PinMAP ↔ PinList 现在可以双向互转。
|
||||
|
||||
---
|
||||
|
||||
### 新增功能
|
||||
|
||||
#### PinList → PinMAP 转换
|
||||
- **PinList 解析**:从 Excel 文件中读取 PinName(A 列)和 Pin 序号(B 列)
|
||||
- **布局计算**:根据用户输入的行数和列数,自动计算四边引脚分配
|
||||
- **逆时针分配**:左上角为 1 脚,沿左边→下边→右边→上边逆时针排列
|
||||
- **PinName 定位**:自动计算 PinName 与序号的相对位置(右/上/左/下)
|
||||
- **周长验证**:检查引脚总数是否匹配 `2×rows + 2×cols − 4`
|
||||
- **优雅降级**:缺失 PinName 自动设为 "NC"
|
||||
|
||||
#### 模板样式引擎
|
||||
- **样式提取**:从模板 xlsx 文件中提取字体、填充、边框、列宽、行高
|
||||
- **样式应用**:将模板样式应用到生成的 PinMAP 输出文件
|
||||
- **优雅降级**:模板不存在或解析失败时自动使用默认样式
|
||||
|
||||
#### 交互式方向选择
|
||||
- **启动菜单**:运行 `python main.py` 显示方向选择(1: MAP→List / 2: List→MAP)
|
||||
- **尺寸输入**:List→MAP 模式需要输入 PinMAP 的行数和列数
|
||||
- **文件选择**:根据方向自动切换文件选择器标题和提示
|
||||
|
||||
#### 数据验证增强
|
||||
- **PinList 验证**:序号连续性、序号唯一性、周长匹配、PinName 完整性
|
||||
- **非 4 倍数提示**:Pin 数量不是 4 的倍数时提示(信息级别)
|
||||
|
||||
---
|
||||
|
||||
### 新增模块
|
||||
|
||||
| 模块 | 代码量 | 说明 |
|
||||
|------|--------|------|
|
||||
| `pinlist_parser.py` | ~80 行 | PinList 文件解析(A/B 列读取 + 排序) |
|
||||
| `pinlist_validator.py` | ~90 行 | PinList 数据验证(连续性/唯一性/周长匹配) |
|
||||
| `pinmap_generator.py` | ~70 行 | PinMAP 生成与输出(布局应用 + 样式) |
|
||||
| `pinmap_layout.py` | ~100 行 | PinMAP 布局计算(四边分配 + 坐标计算) |
|
||||
| `template_reader.py` | ~170 行 | 模板样式提取(fonts/fills/borders/cols/rows) |
|
||||
|
||||
### 更新模块
|
||||
|
||||
| 模块 | 变更说明 |
|
||||
|------|----------|
|
||||
| `main.py` | 增加 `run_list_to_map()` 流程 + 方向选择菜单 |
|
||||
| `file_selector.py` | 增加 `mode` 参数,支持 "map_to_list" / "list_to_map" |
|
||||
| `models.py` | 新增 `PinListEntry`、`EdgePins`、`PinMAPLayout`、`LayoutError` |
|
||||
| `xlsx_writer.py` | 增加 `write_xlsx_with_style()` 支持模板样式写入 |
|
||||
| `validator.py` | 新增 `PinMapValidator` 类,统一验证接口 |
|
||||
|
||||
---
|
||||
|
||||
### 技术实现
|
||||
|
||||
#### 布局算法
|
||||
|
||||
```
|
||||
总引脚数 = 2 × rows + 2 × cols − 4
|
||||
|
||||
左边: rows 个引脚(从上到下)
|
||||
下边: cols − 1 个引脚(从左到右)
|
||||
右边: rows − 2 个引脚(从下到上)
|
||||
上边: cols − 1 个引脚(从右到左)
|
||||
```
|
||||
|
||||
#### 坐标映射
|
||||
|
||||
```
|
||||
左边: 序号 (r, 0) → Name (r, 1) 右侧
|
||||
下边: 序号 (rows, c) → Name (rows-1, c) 上方
|
||||
右边: 序号 (r, cols) → Name (r, cols-1) 左侧
|
||||
上边: 序号 (1, c) → Name (2, c) 下方
|
||||
```
|
||||
|
||||
#### 模板样式提取
|
||||
|
||||
```
|
||||
xl/styles.xml:
|
||||
├── fonts: name, size, bold, italic, color
|
||||
├── fills: pattern_type, fg_color
|
||||
├── borders: top, bottom, left, right (style + color)
|
||||
└── cellXfs: numFmtId, fontId, fillId, borderId, alignment
|
||||
|
||||
xl/worksheets/sheet1.xml:
|
||||
├── cols: column width (min, max, width)
|
||||
└── sheetData: row height
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 测试覆盖
|
||||
|
||||
#### 单元测试(8 个用例)
|
||||
|
||||
| 用例 | 测试内容 | 结果 |
|
||||
|------|----------|------|
|
||||
| `test_4x4_parse` | 4×4 方形 PinMAP 解析 | ✅ |
|
||||
| `test_4x4_validate` | 4×4 方形验证 | ✅ |
|
||||
| `test_missing_names_warning` | PinName 缺失警告 | ✅ |
|
||||
| `test_duplicate_numbers` | 序号重复检测 | ✅ |
|
||||
| `test_gap_in_numbers` | 序号不连续检测 | ✅ |
|
||||
| `test_empty_cells` | 空单元格处理 | ✅ |
|
||||
| `test_no_pins` | 无引脚数据检测 | ✅ |
|
||||
| `test_12pin_square` | 12 引脚方形解析 | ✅ |
|
||||
|
||||
#### 集成测试(6 个用例)
|
||||
|
||||
| 用例 | 输入文件 | 测试内容 | 结果 |
|
||||
|------|----------|----------|------|
|
||||
| TC001 | `sample_4x4.xlsx` | 标准 4×4 转换(8 Pin) | ✅ |
|
||||
| TC002 | `sample_rect.xlsx` | 长方形转换(13 Pin) | ✅ |
|
||||
| TC003 | `error_gap.xlsx` | 序号不连续检测 | ✅ |
|
||||
| TC004 | `error_dup.xlsx` | 序号重复检测 | ✅ |
|
||||
| TC005 | `warning_missing.xlsx` | PinName 缺失警告 | ✅ |
|
||||
| TC006 | `error_empty_a1.xlsx` | A1 为空检测 | ✅ |
|
||||
|
||||
**测试通过率**:100%(14/14)
|
||||
|
||||
---
|
||||
|
||||
### 已知问题
|
||||
|
||||
无
|
||||
|
||||
---
|
||||
|
||||
### 限制
|
||||
|
||||
| 限制项 | 说明 |
|
||||
|--------|------|
|
||||
| 引脚数量 | 建议 < 1000 引脚(典型封装 < 200 引脚,无压力) |
|
||||
| 输入格式 | 仅支持 `.xls` 和 `.xlsx`,不支持 CSV/其他格式 |
|
||||
| 输出格式 | 仅输出 `.xlsx`,不支持 `.xls` |
|
||||
| 工作表 | 仅处理第一个工作表 |
|
||||
| 公式单元格 | 仅读取公式的计算结果,不保留公式本身 |
|
||||
| 命令行方向 | 命令行模式直接传入文件默认走 MAP→List,List→MAP 需交互式选择 |
|
||||
|
||||
---
|
||||
|
||||
### 未来计划
|
||||
|
||||
#### v1.3.0 — 格式增强(规划中)
|
||||
|
||||
- [ ] 支持 `.xls` 格式输出
|
||||
- [ ] 保留原始 Excel 的字体和格式(MAP→List 方向)
|
||||
- [ ] 支持多工作表选择
|
||||
|
||||
#### v1.4.0 — 功能扩展(规划中)
|
||||
|
||||
- [ ] 批量转换(拖拽多个文件)
|
||||
- [ ] CSV 格式输出
|
||||
- [ ] PinMAP 结构可视化预览
|
||||
|
||||
#### v2.0.0 — 架构升级(远期规划)
|
||||
|
||||
- [ ] 支持更多封装类型(BGA、QFN 等)
|
||||
- [ ] 插件式解析器架构
|
||||
- [ ] Web 界面
|
||||
|
||||
---
|
||||
|
||||
### 升级指南
|
||||
|
||||
**首次使用**:直接运行即可,无需升级。
|
||||
|
||||
**从 v1.0.0 升级**:替换 `Code/src/` 目录下所有文件。
|
||||
|
||||
**从 v1.1.0 升级**:替换 `Code/src/` 目录下所有文件。
|
||||
|
||||
---
|
||||
|
||||
### 贡献者
|
||||
|
||||
- 架构设计:Script Architect
|
||||
- 编码实现:Coding Agent × 3
|
||||
- 测试验证:QA Agent
|
||||
- 文档编写:Doc Gen Agent
|
||||
|
||||
---
|
||||
|
||||
### 获取帮助
|
||||
|
||||
- 查看 `QUICKSTART.md` 了解使用方法
|
||||
- 查看 `architecture-design.md` 了解技术细节
|
||||
- 查看 `Test/test_report.md` 了解测试详情
|
||||
|
||||
---
|
||||
|
||||
## v1.0.0 — 2026-05-25
|
||||
|
||||
### 🎉 首次发布
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user