BUG-005: 模板文件名改为 PinMAP-Template.xlsx / PinList-Template.xlsx BUG-006: 布局改为 Number 外侧 + Name 里侧(v1.5.4 最终版) - 从边界往中心:第1圈=Number,第2圈=Name - 上边角点例外处理,15种网格无冲突 - 18/18 单元测试 + 37/37 集成测试全部通过
93 lines
2.8 KiB
Python
93 lines
2.8 KiB
Python
"""PinMAP generator — builds PinMAP cell data and writes to xlsx.
|
||
|
||
Takes layout calculation results and produces:
|
||
1. A cell data dictionary (cell_ref → value)
|
||
2. An xlsx output file with optional template styling
|
||
"""
|
||
|
||
import os
|
||
from typing import Optional
|
||
|
||
from models import PinListEntry, LayoutError
|
||
from pinmap_layout import calculate_layout, get_name_cell
|
||
from template_reader import TemplateStyle
|
||
from utils import rc_to_cell_ref
|
||
from xlsx_writer import write_xlsx, write_xlsx_with_style
|
||
|
||
|
||
def generate_pinmap(
|
||
entries: list[PinListEntry],
|
||
rows: int,
|
||
cols: int,
|
||
package_info: str,
|
||
template_style: Optional[TemplateStyle] = None,
|
||
output_path: Optional[str] = None,
|
||
) -> dict[str, str]:
|
||
"""
|
||
生成 PinMAP 布局并写入文件。
|
||
|
||
Parameters
|
||
----------
|
||
entries : list[PinListEntry]
|
||
PinList 数据
|
||
rows : int
|
||
PinMAP 行数
|
||
cols : int
|
||
PinMAP 列数
|
||
package_info : str
|
||
封装信息(写入 A1)
|
||
template_style : TemplateStyle | None
|
||
模板样式(可选)
|
||
output_path : str | None
|
||
输出文件路径
|
||
|
||
Returns
|
||
-------
|
||
dict[str, str]
|
||
单元格数据字典 {"A1": "封装", "A2": "1", "B2": "Pin1", ...}
|
||
"""
|
||
# 1. 计算布局
|
||
layout = calculate_layout(entries, rows, cols)
|
||
|
||
# 2. 构建单元格数据
|
||
data: dict[str, str] = {}
|
||
data["A1"] = package_info
|
||
|
||
# 先写入 PinName 单元格
|
||
for edge_name, edge in layout.items():
|
||
for (pin_num, pin_name), num_cell in zip(edge.pins, edge.cells):
|
||
name_cell = get_name_cell(num_cell, edge_name, cols=cols)
|
||
name_ref = rc_to_cell_ref(name_cell[0], name_cell[1])
|
||
data[name_ref] = pin_name if pin_name and pin_name.strip() else "NC"
|
||
|
||
# 再写入序号单元格(v1.5.4:无边角共享,每个序号独占一个单元格)
|
||
cell_pins: dict[str, list[str]] = {}
|
||
for edge_name, edge in layout.items():
|
||
for (pin_num, pin_name), num_cell in zip(edge.pins, edge.cells):
|
||
num_ref = rc_to_cell_ref(num_cell[0], num_cell[1])
|
||
if num_ref not in cell_pins:
|
||
cell_pins[num_ref] = []
|
||
cell_pins[num_ref].append(str(pin_num))
|
||
|
||
for num_ref, pins in cell_pins.items():
|
||
data[num_ref] = "/".join(pins)
|
||
|
||
# 3. 写入文件(应用模板样式)
|
||
if output_path:
|
||
if template_style is not None:
|
||
write_xlsx_with_style(data, output_path, template_style)
|
||
else:
|
||
write_xlsx(data, output_path)
|
||
|
||
return data
|
||
|
||
|
||
def generate_output_path(input_path: str) -> str:
|
||
r"""
|
||
根据输入文件路径生成默认输出路径。
|
||
|
||
例如: C:\test\pinlist.xlsx → C:\test\pinlist_PinMAP.xlsx
|
||
"""
|
||
base, _ = os.path.splitext(input_path)
|
||
return base + "_PinMAP.xlsx"
|