news 2026/9/16 10:49:47

用Interactive Html Bom把PCB版图与BOM变成可交互HTML

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Interactive Html Bom把PCB版图与BOM变成可交互HTML

简介:InteractiveHtmlBomForAD 是一款面向 AD(AutoDesk Inventor)的交互式物料清单生成工具,基于前端技术开发,服务电子设计与结构工程等需要频繁维护 BOM 的岗位;它把 AD 工程数据解析为可在浏览器中直接查看和编辑的清单,避免手工整理表格效率低、易出错的问题。压缩包共 30 个文件,以十七个脚本文件为主,另有网页、文档、样式、批处理等类型,整体约139KB;脚本承担核心逻辑与轻量模块,网页用于界面展示,文档说明配置方法,批处理用于环境初始化和清理,目录结构清晰,便于按需修改和二次开发。目前已有1035人学习下载。借助该源码,用户可同时获得源码级核心库、可直接部署的打包产物以及配套说明,快速搭建属于自己的 BOM 生成流程;无论是常规选型、成本核算还是生产备料,都能大幅减少漏项和格式错误,提升数据一致性与协同效率。

1. Interactive Html Bom 是什么,AD 项目为什么需要单独的工具

常规流程里,AD 的 BOM 是一张 CSV 表格,位号、数量、封装齐全,可真到返修和装配环节,你得把表格里的 R27 翻译成板子上焊盘旁边那个点,表格做不到。Interactive Html Bom 把 PCB 版图和 BOM 拼进同一个 HTML:左侧是带网格的板面图,右侧是按值/封装分组的 BOM 列表,点任意元件或 BOM 行,另一侧的对应位号或整组元件全部高亮,坐标、旋转、层信息同步显示。这份 HTML 是自包含单文件,浏览器直接打开,不用起服务、不依赖在线库,适合发给 SMT 工厂或塞进设计评审文档。AD 自己没有这个输出,所以从业者通常攒一个小工具:把 AD 的放置文件、BOM 文件按位号对齐,再灌进 iBOM 渲染模板。Layout 自检、备料核对、评审时定位嫌疑元件,都靠它。

2. AD 侧数据源:放置文件、BOM 与板框尺寸

2.1 放置文件是元件坐标的唯一完整来源

在 PCB 编辑环境用File → Assembly Outputs → Generates pick and place files导出,格式选 CSV、单位选 Metric,得到的就是每个元件一行坐标的文件。这是 iBOM 的骨架,没有它,HTML 里画不出任何东西。

列名含义注意事项
Designator位号,如 R12与原理图一致,BOM 合并时靠它做主键
Footprint封装名,如 C0603不同 AD 封装库写法可能不同,别用来当值
Mid X / Mid Y元件中心坐标单位由导出对话框决定,默认可能是 mil
Ref X / Ref Y元件参考点坐标与原点设置有关,iBOM 一律用 Mid
LayerTop / Bottom底层元件需要额外标识,不能丢
Rotation旋转角度逆时针为正,范围 0-360
Comment元件值常放容值/阻值,也可能放型号

导出对话框里有两个高频坑:单位误选成 mil 会让整个板子尺寸放大 25.4 倍;Format 选成文本制表符分隔后,某些 AD 版本会把带逗号的 Comment 直接切成多列。我都用 CSV 格式,并在脚本里先做列名校验,发现解析异常立即退出,而不是带着错数据往下跑。

2.2 BOM 文件里的位号是折叠的

BOM 用Reports → Bill of Materials生成,AD 默认会按 Comment + Footprint 分组,并把同一组的所有位号写进一个单元格,例如C1,C2,C4-C6R1-R10。这个行为对人工看非常友好,对 iBOM 却是个大麻烦,因为渲染阶段需要的是每个位号独立一行。

导出时至少保留四个字段:Designator、Comment、Footprint、Description。Quantity 列不要直接信任,后面脚本会用展开后的位号数量重新算一遍——这是防呆设计,因为原理图里贴了不焊接的元件位号时,BOM 的 Quantity 可能与展开结果不一致。

2.3 板框尺寸和封装外形怎么补

iBOM 的底板并不需要 Gerber,最简单的方式是拿放置文件全部 Mid 坐标算 min/max,得到一个外接矩形作为板框。对矩形板够用,异形板就得在 AD 里确认原点后,把板框层导出为 DXF/DWG,再转成 SVG 或一组折线坐标。板框的作用有两个:视觉上知道元件在哪,以及后面验证坐标归一化是否正确。

封装外形是另一个缺口。放置文件里没有封装尺寸,只有封装名。常见做法两种:要么内置一张常见封装的近似尺寸表(0603、0805、SOT-23 这类),要么写一个 AD 脚本在 PCB 上遍历 Footprint 对象,把每个位号的包围盒取出来一并导出。前者上手快,后者画出来的元件形状和实物一致,SMT 核对时更直观。

3. 快速 BOM 工具的核心:从 CSV 到 JSON 的合并管线

3.1 以位号为主键对齐两份文件

放置文件逐行一个位号,BOM 逐组一个折叠位号串,合并顺序错了就会丢元件。正确顺序是先读放置文件建索引,再展开 BOM 位号去索引里查坐标。

import csv, re, json, sys def read_pnp(path): rows = {} with open(path, newline='', encoding='utf-8-sig') as f: for row in csv.DictReader(f): ref = row['Designator'].strip() rows[ref] = row return rows def expand_refs(token): refs = [] for part in re.split(r'[\s,;]+', token.strip()): if '-' in part: left, right = part.split('-', 1) prefix = re.sub(r'\d+$', '', left) n1 = int(re.findall(r'\d+', left)[-1]) n2 = int(re.findall(r'\d+', right)[-1]) refs += [f"{prefix}{i}" for i in range(n1, n2 + 1)] else: refs.append(part) return refs

read_pnp把放置文件变成{位号: 行数据}的字典,因为后面要被 BOM 组的位号反复查询;expand_refs负责把C4-C6这类区间展开成三个独立位号,同时容忍空格、逗号、分号混合分隔。这段代码对 AD 导出的 BOM 做的唯一假设是位号列存在,凡是列名带designatorDesignator位号都先归一化再使用,避免不同模板之间来回改。

3.2 分组、数量重算与位号压缩

拿到每个位号的坐标和值之后,按Comment + Footprint重新分组,再用压缩算法把同组位号折叠回区间表示,这样右侧 BOM 列表不会出现几十行单条位号。

def compress_refs(refs): parsed = [] for r in refs: pre = re.sub(r'\d+$', '', r) num = int(re.findall(r'\d+', r)[-1]) parsed.append((pre, num)) parsed.sort(key=lambda x: (x[0], x[1])) out, cur = [], [] for pre, num in parsed: if cur and (pre != cur[-1][0] or num != cur[-1][1] + 1): out.append(cur); cur = [] cur.append((pre, num)) out.append(cur) parts = [] for group in out: pre = group[0][0] nums = [n for _, n in group] parts.append(pre + str(nums[0]) if len(nums) == 1 else f"{pre}{nums[0]}-{pre}{nums[-1]}") return ','.join(parts) def build_json(pnp_path, bom_path, units='mm'): pnp = read_pnp(pnp_path) groups = [] with open(bom_path, newline='', encoding='utf-8-sig') as f: for row in csv.DictReader(f): refs = [] for token in row['Designator'].split(','): refs += expand_refs(token) refs = [r for r in refs if r in pnp] if not refs: continue key = (row['Comment'].strip(), row['Footprint'].strip()) groups.append({ 'value': key[0], 'footprint': key[1], 'refs': sorted(refs), 'qty': len(refs) }) return {'units': units, 'groups': groups}

这段代码把 BOM 的每一组展开后,逐个位号去放置文件字典里查存在性,查不到的直接丢弃并留下隐患,所以在丢弃前我会往终端打印WARN: C90 not in PnP。重新计算的qty以实际存在于 PCB 上的位号数为准,避免 BOM 里残留了不参与装配的元件。压缩函数里R1-R10这类连续区间被合并,位号乱序也会先排序再压缩,HTML 侧列表可读性会好很多。

3.3 坐标转换、底层元件与旋转方向

AD 的坐标系以左下角为原点、Y 轴向上,而浏览器画布的 Y 轴向下,渲染前必须翻转。常用的做法是先算全部 Mid 坐标的 min/max,再把 Y 翻转后平移到画布内。

def normalize_components(pnp_rows, board): components = [] for ref, row in pnp_rows.items(): x = float(row['Mid X']) y = float(row['Mid Y']) if row['Layer'].lower().startswith('bottom'): layer = 'bottom' else: layer = 'top' components.append({ 'ref': ref, 'layer': layer, 'x': x, 'y': y, 'rot': float(row['Rotation']) % 360, 'value': row.get('Comment', '').strip(), 'footprint': row.get('Footprint', '').strip() }) xs = [c['x'] for c in components] ys = [c['y'] for c in components] board.update({'minX': min(xs), 'minY': min(ys), 'maxX': max(xs), 'maxY': max(ys)}) return components

归一化时注意两点:旋转角度对 360 取模,避免出现 450 这样的脏数据;底层元件不在这里翻转坐标,只标记layer: bottom,翻转交给渲染层统一处理。这样顶层元件和底层元件在同一个板面坐标系里,做自检时切到“仅底层”视图也不会有一半元件跑到板外。

4. 用 InteractiveHtmlBom 风格的 HTML 模板把 JSON 渲染成单文件

4.1 数据内联与 SVG 画布初始化

渲染层不必依赖任何框架,把第 3 章生成的 JSON 直接内联进 HTML,再用原生 SVG 画元件矩形即可。单文件的关键在于数据不经过外部请求,全部写在<script type="application/json">里。

<!DOCTYPE html> <html> <head><meta charset="utf-8"><title>iBOM</title> <style> body{margin:0;display:flex;font-family:Consolas,monospace} #panel{width:60%;height:100vh} #bom{width:40%;height:100vh;overflow:auto;font-size:13px} rect.comp{fill:#d4e6f1;stroke:#2e86c1;cursor:pointer} rect.comp.hl{fill:#f39c12;stroke:#e67e22} </style></head> <body> <div id="panel"><svg id="board" width="100%" height="100%"></svg></div> <div id="bom"></div> <script type="application/json" id="bom-data"> { "units": "mm", "board": {"minX": 0, "minY": 0, "maxX": 100, "maxY": 80}, "groups": [ {"value": "100nF", "footprint": "C0603", "refs": ["C1", "C2"], "qty": 2} ], "components": [ {"ref": "C1", "layer": "top", "x": 10.16, "y": 20.32, "rot": 90, "value": "100nF", "footprint": "C0603"} ] } </script> <script> const raw = JSON.parse(document.getElementById('bom-data').textContent); const svg = document.getElementById('board'); const B = raw.board, pad = 12; const sx = (svg.clientWidth - pad * 2) / (B.maxX - B.minX); const sy = (svg.clientHeight - pad * 2) / (B.maxY - B.minY); const scale = Math.min(sx, sy); const px = x => pad + (x - B.minX) * scale; const py = y => pad + (B.maxY - y) * scale; </script> </body> </html>

pxpy完成从毫米到像素的映射,py里的一次maxY - y就是解决 AD 与浏览器坐标系差异的关键。数据 JSON 中 board 的外接矩形由脚本计算,HTML 模板只负责按比例缩放。这样只要 AD 导出的坐标没错,渲染位置就不会系统性偏移。

4.2 点击联动、BOM 分组高亮与过滤器

元件渲染和 BOM 面板联动是交互体验的核心,逻辑拆成三个函数:渲染元件、渲染 BOM 行、选中状态同步。

for (const c of raw.components) { const r = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); let w = 3 * scale, h = 1.5 * scale; // 无封装尺寸时的默认占位 r.setAttribute('class', 'comp'); r.setAttribute('data-ref', c.ref); r.setAttribute('x', px(c.x) - w / 2); r.setAttribute('y', py(c.y) - h / 2); r.setAttribute('width', w); r.setAttribute('height', h); r.setAttribute('transform', `rotate(${-c.rot} ${px(c.x)} ${py(c.y)})`); r.addEventListener('click', () => highlightRef(c.ref)); svg.appendChild(r); } function highlightRef(ref) { document.querySelectorAll('.comp').forEach(el => el.classList.toggle('hl', el.dataset.ref === ref)); const group = raw.groups.find(g => g.refs.includes(ref)); renderBom(group ? group.refs : [ref]); } function renderBom(visitedRefs) { const bom = document.getElementById('bom'); bom.innerHTML = raw.groups.map((g, i) => { const hit = g.refs.some(r => visitedRefs.includes(r)); return `<div class="bom-row">python ad2json.py pick_and_place.txt bom_export.csv \ --out iBOM_MOTOR_V2.html \ --units mm \ --group-by comment:footprint \ --compress-refs \ --check-duplicate-refs

参数含义分别是:--out指定输出文件,最终是自包含 HTML;--units声明放置文件单位,mils 时内部先除以 25.4 再参与计算;--group-by控制 BOM 分组维度,默认按值和封装;--compress-refs把连续位号压缩成区间;--check-duplicate-refs在检测到同一 bit 位号出现两次时直接报错。这个脚本生成时把 JSON 嵌入 HTML 的同时会额外写一份iBOM_data.json,供后续自动化校验用,不参与渲染。

配置项默认值作用
unitsmm决定坐标是否做 mil 换算
scaleauto画布内自动适配,不建议手工指定
highlightColor#f39c12选中元件填充色,按封装类型可扩展
showRefTextfalse是否在每个元件旁显示位号文本
bottomLayerColor#b0bec5底层元件独立配色,避免与顶层混淆

大板子几千个元件时,SVG 节点数量会明显拉高内存占用。如果发现拖动卡顿,我一般把showRefText关掉,只保留点击后显示位号;再不行就把元件渲染从rect换成circle,节点更轻,视觉上也够用。

5. 拿到 HTML 后怎么确认它没有张冠李戴

5.1 用钻孔文件校板框

打开 AD 导出的 NC Drill 文件,Excellon 格式里所有钻孔的 X/Y 坐标范围,理论上应该和放置文件的外接矩形吻合。用一个三五行的小脚本读一遍,和iBOM_data.json里的board字段对比,容差留 0.05mm。

python - <<'PY' import json, re d = json.load(open('iBOM_data.json')) xs, ys = [], [] for line in open('drill.TXT', errors='ignore'): m = re.search(r'X(-?\d+\.?\d*)Y(-?\d+\.?\d*)', line) if m: xs.append(float(m.group(1)) / 25.4) ys.append(float(m.group(2)) / 25.4) b = d['board'] assert abs(min(xs) - b['minX']) < 0.05 assert abs(max(xs) - b['maxX']) < 0.05 print('board ok', min(xs), max(xs), min(ys), max(ys)) PY

这段命令把钻孔文件的 mil 坐标统一除以 25.4 转成毫米,再与 iBOM 板框对比。板框对不上时,多半是放置文件单位选错或 AD 原点与钻孔原点不一致,趁早发现比焊完料再核对成本低得多。

5.2 位号抽查与重复位号拦截

随机抽十个位号,在 AD 里用快捷键跳转,再回到 HTML 点击同一元件,观察高亮位置是否一致。注意看底层元件:AD 里旋转 90 度的 Bottom 元件,HTML 里应该显示为旋转负 90 度,这是镜像关系决定的,不是 bug。把这条写进检查清单里,因为绝大多数人第一次看到 Bottom 元件方向都会怀疑工具坏了。

批量验证的习惯是保留ad2json.py--check-duplicate-refs,这是我最常开的一个开关。AD 工程中复制粘贴模块时容易产生重复位号,普通 BOM 看不出来,iBOM 一渲染就会出现两个元件抢一个位号,点谁都是高亮俩。

5.3 大板性能与文件体积的控制

几千个元件的板子,HTML 文件体积主要来自内联 JSON 和 SVG 节点。--compress-refs开启后,BOM 分组里的位号数组会以区间字符串存储,渲染时再展开,文件体积能省 30% 左右。若还想再快,把丝印文本、板框以外的装饰层去掉,只保留元件矩形和 BOM 列表,交互流畅度提升明显。做完这些,把 HTML 和iBOM_data.json一起放进工程仓库的 docs 目录,设计评审时浏览器一开,翻三份文件的功夫全省了。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 10:48:59

SSM+MySQL决策树就业预测系统:从数据表到算法落地

简介&#xff1a;面向高校计算机相关专业毕业设计及期末大作业场景&#xff0c;这份基于SSM与Mysql的决策树算法大学生就业预测系统完整资料包&#xff0c;含源码、论文、开题报告、部署文档、运行说明和演示视频&#xff0c;可支撑从环境搭建、算法落地到系统演示的全流程。压…

作者头像 李华
网站建设 2026/9/16 10:48:58

企业数据标准化实践:从混乱到高效的四步法

1. 数据混乱的根源与标准化价值每次接手新项目时&#xff0c;最头疼的就是看到十几个部门交上来的数据表格——字段命名五花八门&#xff08;有叫"用户ID"的&#xff0c;有写"customer_code"的&#xff09;&#xff0c;日期格式千奇百怪&#xff08;2023/0…

作者头像 李华
网站建设 2026/9/16 10:48:09

Workflow Connector MCP Server MCP 服务说明文档

1. 服务概述一句话简介&#xff1a;AI Agent工作流连接器MCP Server - 连接SaaS服务、创建自动化工作流、管理Webhook、提供工作流模板服务名称&#xff1a;Workflow Connector MCP Server版本号&#xff1a;最新版本开发者/提供方&#xff1a;zhaohongyuziranerran协议类型&am…

作者头像 李华
网站建设 2026/9/16 10:47:51

SpringBoot+微信小程序打造乐器社区平台实战

1. 项目背景与核心价值作为一个在Web开发领域摸爬滚打多年的老码农&#xff0c;我见过太多千篇一律的毕业设计项目。但这个乐器社区平台确实让我眼前一亮——它巧妙地将传统SpringBoot后端与微信小程序前端结合&#xff0c;打造了一个完整的乐器爱好者生态圈。不同于简单的CRUD…

作者头像 李华