feat: PinMAP转PinList v1.2.0 - 新增PinList转PinMAP反向转换功能
This commit is contained in:
@@ -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]` | 转换完成 | 显示输出文件路径和统计信息 |
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user