
做2D排样2D Nesting的朋友无论是用商业套料软件还是自己写脚本恐怕都遇到过同一个坎图形文件拖进去很容易零件数据却不知道往哪里填。排样引擎真正要的不是一张画满轮廓的图而是一份它能读懂的零件清单——哪个零件要做多少个、多厚、什么材质、允不允许旋转。这份清单在绝大多数软件里就是CSV文件。围绕这个主题我结合自己用过的几款排样工具和踩过的坑把如何定义一份让排样软件满意的CSV零件数据这件事完整梳理一遍。这篇文章不会只讲点哪里导入而是会把字段设计、生成方式、编码陷阱、验证思路和排查路线都串起来。适合正在做激光切割、钣金下料、木工开料或任何涉及二维套料的工程师阅读也适合写排样脚本的开发人员参考。1. 先把CSV在2D排样流程中的真实位置摆正1.1 排样引擎需要的不只是图形很多第一次接触2D Nesting的人会误以为排样软件主要吃DXF或者DWG把图导进去就能自动套料。这个理解只对了一半。图形文件解决的是零件长什么样的问题而排样引擎在计算时还需要知道这个零件要做多少个用什么板材板厚多少纹理方向能不能转这些工艺属性。我最早做套料的时候直接在CAD里手动画完所有零件然后一股脑导入排版模块结果软件只识别出了第一块板上的几个图形数量完全乱套。后来才醒悟商业排样软件的标准输入方式通常是两条腿走路DXF或DWG提供轮廓几何CSV提供零件属性。两者通过零件编号Part ID关联起来。CSV里的每一行对应一种零件而不是一个物理零件。所以CSV在排样流程中的定位可以理解成一张加工任务单。图纸负责描述形状CSV负责描述做多少、用什么做、有什么限制。缺了CSV再漂亮的DXF在排样引擎眼里也只是一堆没有归属的线条。1.2 一份零件CSV背后是完整的工艺数据用CSV承载零件数据本质上是在做信息建模。它把三维世界里的零件信息降维成二维表格供排样程序逐行解析。排样计算时涉及的数据通常可以分为四层识别层零件编号、零件名称、所属图号或订单号。数量层单个零件需要的数量以及是否按套Set计算。几何层零件的外形尺寸长、宽有时还包括面积和周长。工艺层板材材质、厚度、允许旋转角度、纹理方向、配对关系、优先级。这四层信息里识别层和数量层是CSV必须解决的几何层有争议——因为图形文件里理论上已经包含轮廓尺寸但部分软件的排样内核确实会优先读取CSV里的宽高来生成外接矩形用于快速碰撞检测再用DXF里的实际轮廓做精细排样。工艺层字段越多排样结果越贴近车间真实加工条件比如不允许旋转的零件如果强行旋转虽然排版密度上去了但后续丝印方向、木纹方向全错了得不偿失。1.3 为什么偏偏是CSV而不是Excel或数据库这里有一个经常被问到的点好多软件明明支持Excel为什么还要强调CSV原因很实际。CSV是纯文本格式没有宏、没有隐藏工作表、没有格式干扰每一行就是一条记录解析逻辑极其简单任何语言一个文件读取操作就能搞定。Excel格式本质上是Zip压缩包里面是多个XML文件解析起来复杂度高一个量级而且同一列里出现数字和文本混合时程序化读取会遇到很多类型推断问题。排样软件面对的是上万个零件的数据量用CSV传输数据最稳妥。它跨平台、跨语言、跨区域设置的表现都可控排样引擎只要按逗号或分号切分每一行就能工作。对使用者来说CSV还可以直接用记事本、Notepad、VS Code打开检查不用启动庞大的办公软件。这也是为什么几乎所有排样软件的文档里导入零件数据的示例文件都是CSV。2. 零件数据CSV的字段设计最小集与进阶参数2.1 无论如何都要有的核心字段不同排样软件对CSV表头的要求不完全一致但抽掉外壳核心字段高度相似。我整理了一张通用字段表任何一个排样项目基本都能映射到这个框架上字段名类型必填说明Part ID字符串是零件唯一编号与DXF中的图元/块名对应Quantity整数是该零件的需求数量Material字符串是材质名称如Steel、Aluminum、MDFThickness浮点数是板厚单位mmWidth浮点数是零件外形宽度单位mmLength浮点数是零件外形长度单位mmPart ID是关联图形和属性的关键。很多软件要求CSV里的Part ID必须严格匹配DXF文件里的块名、图层名或特定属性值大小写都不能差。如果两头对不上软件通常会在日志里标注未找到对应图形一类的警告但不会阻止你继续操作结果就是零件进了清单却没进排版区事后核对才发现少了一大片。Quantity最好写成纯数字不要带个件pcs这类单位后缀。排样软件解析整数时遇到非数字字符可能直接报错或者静默地把该行当成0处理。Thickness字段同理用12.0而不是12mm。单位必须全项目统一最常用的是毫米但如果你的软件默认英寸那所有尺寸字段都要用英寸值混用单位导致成品放大的情况我见过不止一次。2.2 能显著提升排样品质的进阶字段最小字段只能让排样器跑起来真要让排样结果能直接下车间进阶字段更重要。我按实用度排序说明Rotatable允许旋转布尔值或枚举值0表示禁止旋转1表示可旋转90度2表示任意角度。木工开料和带纹理的钣金件通常禁止旋转普通金属板件则建议放开旋转以提升材料利用率。Grain Direction纹理方向字符串或布尔值标识零件是否有纹理方向要求。这个字段在排样器内部起作用的方式是有方向要求的零件只能以0度或180度摆放不能做90度旋转。Pair ID配对编号用于成对出现的零件比如左右对称件。指定配对关系后排样器会尽量让成对零件处在同一张板上方便后续折弯和焊接。Priority优先级整数。高优先级的零件优先占用板材的优质区域低优先级零件用剩余边角料填充。Mirror允许镜像布尔值。某些冲压件镜像后模具方向不同需要明确标识。这些字段不是所有软件都支持而且同一个意思在不同软件里字段名可能完全不同。比如有的软件用Allow Rotation有的用Rotation Limit。所以拿到一个排样项目的CSV模板时先打开软件的示例文件研究字段名比对着文档猜效率高得多。2.3 理解尺寸字段与轮廓文件的关系这里要展开讲一个新手最容易困惑的点既然DXF里已经有轮廓了CSV里为什么还要Width和Length原因在于排样算法的数据结构。排样引擎在做碰撞检测和板材摆放时第一阶段用的是零件的外接矩形Bounding Box快速粗排定位第二阶段才用精确多边形做边界贴合和嵌套计算。CSV里的Width和Length承担的是第一阶段的加速职责。如果这个尺寸和DXF里的实际轮廓偏差过大粗排阶段就会算出错误的占位导致零件相互重叠或离得太远。另一个实际场景是有些企业从ERP导出的BOM里只有长宽和数量没有对应图纸。这时候排样软件可以只用CSV的矩形数据做矩形排样先估算材料用量等图纸到位再做精确排样。所以尺寸字段要尽力保证准确如果你只有DXF而没有BOM尺寸宁可先用CAD的测量工具量一遍再填也别随手估一个。2.4 一份可直接套用的字段模板下面是我在实际项目中用过的模板兼容性好大多数软件都能识别Part ID,Quantity,Material,Thickness,Width,Length,Rotatable,Priority P-001,12,Steel_Q235,2.0,150.0,220.0,1,2 P-002,8,Steel_Q235,2.0,80.0,410.0,1,2 P-003,4,Al5052,1.5,120.0,120.0,0,1 P-004,20,MDF_18mm,18.0,60.0,900.0,0,3我习惯把Rotatable和Priority这类不一定每个软件都认的字段放在最后这样即使软件只读取前六列也不会导致列错位。类似的字段顺序策略在对接不同客户提供的CSV时非常实用。3. 三种生成零件CSV的实用路径3.1 手工整理适合小批量与打样项目初期或者打样阶段零件数量少用手工整理完全够用。操作上最顺手的方式是打开Excel按模板填入数据然后另存为CSV。需要注意Excel的默认编码问题我在下一章会详细讲这里先提醒一句尽量选择CSV UTF-8逗号分隔这个选项而不是直接点另存为选CSV。手工整理有个隐藏陷阱零件编号里的前导零。如果零件号是00123Excel默认会把它当数字处理另存为CSV后前导零直接消失变成123DXF里却还有一个叫00123的零件两边匹配不上。解决办法是在Excel里先把零件号列设为文本格式或者自定义格式为00000。即使这样导入排样软件后也要在数据预览里确认编号没变。对于打样场景手工整理的流程通常是先在CAD里创建好零件块再照着块名逐行填CSV。花十分钟把表填完换来的是排样结果的确定性。手填时我习惯每条记录写完立刻复查一遍数量这个环节出错率最高往往不是填错行而是漏填了某种零件。3.2 Excel/BOM导出适合已有物料清单的场景如果公司已经有ERP或者生产BOM零件数据通常不需要手敲直接从系统导出Excel再整理成CSV就行。这个路径下最大的工作量在字段映射。ERP里的物料编码对应CSV里的Part ID需求数量对应Quantity规格长宽对应Width和Length材质描述对应Material。我处理过一次从用友系统导出的BOM物料编码列里混着空格和中文全角括号数量列里有的带单位后缀长宽列是150*220这种合并格式。这些脏数据直接进排样CSV基本是废的需要清洗。清洗的规则其实就几条去空格、统一大小写、拆开合并尺寸列、剔除单位后缀。用Excel的函数能干但数据量大或者规则复杂时建议交给Python脚本处理可持续性完全不一样。BOM导出的一个常见误区是把所有层级都倒出来。一张订单可能有装配体、子装配体、单件三层结构排样只需要最底层的单件数据。导出前一定要做过滤只保留自制件和原材料级的零件外购件和子装配体要在SQL或Excel里提前剔除。3.3 Python脚本生成大批量自动化的正解排样项目一旦上了规模比如一次性处理上千种零件脚本生成是唯一靠谱的方式。最常见的做法是直接从DXF文件里提取零件块信息自动生成CSV。这样Part ID和尺寸字段都不用二次录入天然不会对不上。我写过一个简单的脚本核心思路是用ezdxf库读取DXF里的块定义取块的边界框作为Width和Length再把块名按规则映射到物料编码。代码大概长这样import csv import ezdxf doc ezdxf.readfile(parts.dxf) msp doc.modelspace() parts {} for block_ref in msp.query(INSERT): block_name block_ref.dxf.name block doc.blocks.get(block_name) extents block.bbox() # ezdxf 0.18 支持快速包围盒 width extents.size.x length extents.size.y parts[block_name] { width: round(width, 2), length: round(length, 2), } with open(parts_data.csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([Part ID, Quantity, Material, Thickness, Width, Length]) for pid, geom in parts.items(): writer.writerow([pid, 1, Steel_Q235, 2.0, geom[width], geom[length]])这里quantity写死为1实际项目中通常要从BOM导入。更完整的做法是脚本接受一个BOM文件作为输入BOM里有每个块名的需求数量脚本再解析DXF补全尺寸。用脚本的好处是整个过程可重复图纸更新了重新跑一遍就能得到新CSV不会出现CSV和DXF版本不一致这种经典事故。脚本生成还有一个附带好处可以在生成CSV时顺手写一个校验文件记录每种零件的面积之和、数量之和方便后面和排样结果对照。4. 导入时最容易翻车的编码、分隔符和数值格式4.1 编码问题Excel另存为的默认编码与乱码这一节值得每一个做排样的人认真看因为编码问题占CSV导入失败的半壁江山。Windows上的Excel直接另存为CSV时默认保存为ANSI编码对于简体中文系统就是GBK。如果你的CSV里只有ASCII字符GBK和UTF-8没区别能正常导入。一旦零件名称或材质里有中文比如MDF_中纤板用GBK编码的文件到了一个以UTF-8为默认编码的排样软件里中文就会乱码。更隐蔽的是UTF-8 BOM问题。大家知道Windows记事本存UTF-8文件时会加三个字节的BOM头EF BB BF很多排样软件的CSV解析器并不会跳过BOM于是第一列表头就变成了\ufeffPart ID。有些软件容错性强能自动处理有些则直接提示找不到Part ID列。这个问题在Linux服务器上运行的排样服务里尤其常见。我自己的处理原则是统一使用UTF-8无BOM编码用VS Code或Notepad把文件另存一遍。Excel保存的CSV如果实在想保留原样就在导入排样软件前用脚本批量转一次编码。Python里一行就能搞定with open(raw.csv, r, encodinggbk) as f: content f.read() with open(final.csv, w, encodingutf-8-sig) as f: f.write(content)注意这段代码读出来再写回去实际生产环境里我会用errorsreplace先检查一遍有没有无法解码的字符避免静默丢数据。4.2 分隔符逗号还是分号这由区域设置决定CSV的全称是Comma-Separated Values按理说分隔符就是逗号但实操里经常碰到用分号或者Tab分隔的文件。原因在于欧洲一些国家和地区的系统区域设置里列表分隔符默认就是分号Excel另存CSV时就会用分号替代逗号。导入排样软件时导入后所有零件变成一个长字符串或者明明分了六列软件只认出一列八成就是分隔符不匹配。解决办法有三个在源系统里改区域设置后重新导出在排样软件的导入界面选择分隔符类型用文本编辑器全局替换分号为逗号。但全局替换有风险如果材质名称里本来就带着分号或逗号直接替换会把字段内容截断。更稳妥的做法是用支持CSV引号解析的脚本去转换import csv with open(input.csv, r, encodingutf-8) as f: reader csv.reader(f, delimiter;) rows list(reader) with open(output.csv, w, encodingutf-8, newline) as f: writer csv.writer(f, delimiter,) writer.writerows(rows)csv库会自动处理引号包裹的字段逗号和分号只要被双引号包住就不会被错误切分。4.3 前导零丢失与科学计数法的隐形坑前面提过前导零问题实际发生频率比我预想的高得多。有一次项目里所有零件编号是01001这种格式我从ERP导出的Excel BOM里看着还正常另存为CSV后导入排样软件日志里一片找不到零件01001的轮廓最后定位到的原因是Excel把01001当成数字1001保存了。看起来只差一个0匹配关系全断。长数字科学计数法同样坑人。如果零件编号超过11位Excel会显示为8.20123E12这种科学计数法形式写入CSV的也是这个字符串排样软件拿它去匹配DXF块名必然失败。应对技巧很简单在Excel里把编号列设置为文本格式或者直接用记事本做另存为。如果数据已经在CSV里变成了1001而你知道原本是01001可以在Python里用zfill补回去part_id 1001 fixed part_id.zfill(5) # 得到 01001但最理想的还是源头控制数据从ERP出来之前就定义好字段类型。4.4 行结束符、空行和引号转义行结束符是个存在感很低但偶尔发作的问题。Windows系统的CSV用CRLF\r\n作为行结束Linux和macOS通常用LF\n。绝大多数解析器两种都认识但一些老旧的排样组件可能只认CRLF导致导入后最后一行数据不完整或者所有行挤成一团。如果遇到这种情况用VS Code右下角把行结束符统一成CRLF再保存通常能解决。空行问题常出现在Excel导出的CSV末尾。Excel有时会在数据末尾多写一个空行解析器如果不跳过空行会在数据集里多出一条全是空值的记录。有的排样软件会把空行当成数量为0的零件有的直接崩溃。导入前用文本编辑器检查一下文件末尾有没有空行随手删掉能省不少事。引号转义则关系到字段内容本身带逗号的情况。按CSV规范字段里如果包含逗号、引号或换行需要用双引号把整个字段包起来字段内的双引号用两个双引号转义。比如材质名称写成Steel, Q235解析器能正确识别为一个字段。但有些排样软件的解析器实现不完整不支持引号转义看到引号就直接报错。这种时候最省事的办法是让所有字段内容里都不要出现逗号材质名称里用空格或者连字符替代。5. 从CSV到排样结果一次完整的验证流程5.1 导入前的文件体检拿到CSV之后第一件事不是急着导入排样软件而是先做一次文件体检。我用的是最朴素也最有效的方法用VS Code或Notepad打开文件肉眼扫一遍。体检清单如下第一行表头是否符合软件要求的字段名。每一行的列数是否一致可以用文本编辑器的列模式选中看对齐情况。所有Part ID是否都有对应的DXF块名。Quantity列是否有0或负数。所有数值列的小数点是否都是英文句点。文件编码是UTF-8无BOM还是别的格式。文件末尾是否有空行。这些检查看起来琐碎但能拦截掉八成以上的导入失败。其中列数一致性检查最容易被忽略因为Excel里复制单元格时不注意会把两个字段塞进一个单元格导出的CSV这一行就只有七列而其他行有八列排样解析器按固定索引取字段时就会取到错位的值。5.2 用脚本校验数据的数量与字段完整性体检完了我习惯再用Python脚本做一道程序化校验尤其是在处理几千行数据的时候。脚本做三件事统计总零件数、找出缺失字段的记录、检查Part ID是否有重复。import csv from collections import Counter with open(parts_data.csv, r, encodingutf-8) as f: reader csv.DictReader(f) rows list(reader) total_quantity 0 part_counter Counter() missing_fields [] for idx, row in enumerate(rows, start2): if not row.get(Part ID) or not row.get(Quantity): missing_fields.append(idx) try: qty int(row.get(Quantity, 0)) total_quantity qty except ValueError: missing_fields.append(idx) continue part_counter[row[Part ID]] qty print(f总零件数: {total_quantity}) print(f零件种类数: {len(part_counter)}) print(f缺失字段的行: {missing_fields}) for pid, qty in part_counter.items(): if qty 0: print(f异常数量: {pid}: {qty})这里有一段需要注意如果单个零件出现多次且Quantity求和后与BOM对不上就要回头查是不是Part ID写重了。有些软件允许同一Part ID多行存在然后自动累加有些则会直接报错行为差异很大尽量保证一个Part ID只出现一行。5.3 在排样软件里核对最终结果导入成功后不能直接看排样图就完事。我的习惯是在生成预览后立刻做三组核对第一组零件清单核对。排样软件的零件列表里每个Part ID后面的数量是否和CSV里的Quantity一致。这个环节最能暴露匹配问题——如果某零件在列表里数量显示为0或者缺失说明Part ID和DXF块名没对上是大概率事件。第二组板材利用率核对。先算一块理论上的简单排样比如只放同一种矩形零件把软件算出的利用率和手算值对比偏差超过两个百分点就要警惕是不是尺寸字段或间距设置有误。这个数据同时也可以反过来验证CSV里的Width和Length是否正确。第三组输出报告核对。排样软件生成的下料报告或切割代码里会注明每张板上有哪些零件。抽查其中一块板和生产工单对照确认零件归属和数量都正确。这一步虽然繁琐但能让排样流程形成一个完整闭环。6. 数据读不进去时按这条路线排查6.1 六个检查点按顺序走一遍CSV导入报错或者数据读不进去的时候按什么顺序排查直接决定了你要花多少时间。我给团队定过一个固定排查路线按概率从高到低排列编码有没有中文乱码第一列字段名前面有没有BOM字符。分隔符导入界面里预览的列数对不对如果是整段挤在一列先查分隔符。表头字段名是否和软件要求完全一致包括大小写和下划线。数据类型数量列有没有非数字字符尺寸列有没有单位后缀。Part ID匹配CSV里的零件编号和DXF块名能否对应上重点看空格和零。列顺序软件是固定列顺序还是按表头识别这决定了调整空间。这六个检查点每一步都可以用文本编辑器直接确认。我见过太多人抱着排样软件的报错日志反复研究却忘了先用记事本看一眼文件本身——其实答案早就写在那里只是没看。比如热词里出现的csv log unsuccessful这类日志经常是某一行数据格式不对导致整批导入中断。处理方式很简单把日志指向的行号打开看一眼改掉那一行的坏数据重新导入。没必要为了一条脏数据反复整体调配置。6.2 一个容易被忽略的列错位陷阱有一个情况特别容易误导人CSV文件本身没问题软件也显示导入成功但实际数据全是错的。这通常发生在软件按固定列顺序读取、而你的CSV列顺序又不匹配的时候。比如软件认为第二列是Quantity你的第二列却是Material程序不报错把Steel_Q235当成数量去解析。如果能解析成数字就可能忽略解析不了就报类型错误最隐蔽的是恰好某个材质名是63直接被当成数量63用了这种错误排查起来极耗时间。应对办法是导入后立即在软件的数据预览界面里逐列核对不要只看零件数量总数。如果软件没有预览功能就导入一种已知数量很少的测试CSV比如三行数据这样即使读错位了也容易发现。6.3 排查工具的推荐除了排样软件自带的日志我常用的排查工具就三样VS Code看编码、看BOM、看行结束符右下角状态栏都能直接显示。Python的csv库做分隔符转换、列数检查、字段校验批量处理效率极高。Excel的数据预览打开CSV时它会自动按当前区域设置切分可以用来快速观察列结构。但注意Excel打开再保存CSV会改动编码和格式所以Excel只用来看不要用来存。这三个工具组合起来基本覆盖了我遇到过的所有CSV导入问题。最后再分享一个个人习惯每次排样项目开始前我会先把CSV模板和一份填写说明放在共享目录里团队所有人都按同一套字段规则做事。CSV是排样流程里最不起眼的一环但因为它和所有环节都相关反而值得花二十分钟做一次标准化。模板一旦定下来后面每个项目的效率都会明显不一样。