' ============================================================================= ' NX Journal: 参数化母模 + 参数表 → 批量导出 STEP (欧霓博目录软件专用) ' ' ▍这个脚本干什么 ' 逐行读取 CSV 参数表 (每行 = 一个型号: 型号编码 + bore/stroke/magnet/mount... + step_file), ' 对每个型号: 修改母模表达式 → 更新模型 → 导出 STEP214 文件。 ' ★ 已按 step_file 去重: 多个型号行共用同一文件时只导出一次 (52,154 行型号 ' 只会导出唯一几何文件, 例如 KC 系列 2,772 个)。断点续跑: 输出目录已存在的文件会跳过。 ' ' ▍使用前置 (母模要求, 详见《NX母模建模操作说明书.md》) ' 1) 母模中所有"会变"尺寸必须用表达式驱动, 表达式名与 CSV 列名一字不差 ' 2) 磁石槽/安装形式/双轴等"有无"特征 → 按表达式抑制 (Suppression by Expression) ' 3) 建模验收: 手动改 bore/stroke/magOn/mountIdx 各验证过重建无误 ' ' ▍运行方法 ' NX 打开母模 → 菜单 工具 → 日记 → 播放 → 选本文件 ' (注意: Ctrl+U 只认 .dll, 本 .vb 必须走"日记→播放") ' ' ▍CONFIG 区修改清单 (建模工程师每次只改这里) ' [1] csvPath / outDir 两个路径 ' [2] exprMap — 尺寸映射: NX 表达式名 → CSV 列名 (新增独立尺寸表达式就加一行) ' [3] switchRules — 枚举开关: {CSV列名, 列值, NX表达式名, 表达式值} ' 例: 磁石列 "M" → magOn=1; 固定形式 "FA" → mountIdx=1 (取值按母模约定) ' [4] exportStl / stlOutDir — 同步导出 STL 网格 (桌面目录软件窗口内 3D 预览用, 开源 Helix 渲染) ' STL 文件名与 STEP 同名 (.stl), 放在 catalog\mesh\ 目录; 不需要窗口内预览就 exportStl = False ' ' ▍注意 ' - DexBuilder 导出接口 NX 10 ~ NX 2506 兼容; 若你的 NX 版本 API 有差异, ' 用【工具→日记→录制】录一次 文件→导出→STEP214, 替换 ExportStep 函数体。 ' - 中文注释需 UTF-8 带 BOM (改完跑 fix-bom.ps1), 否则 NX 读乱。 ' - 导出失败的行不会中断整体, 最后汇总统计写进 NX 信息窗口 (ListingWindow)。 ' ============================================================================= Option Strict Off Imports System Imports System.IO Imports NXOpen Imports NXOpen.UF Module BatchStepExport Dim theSession As Session = Session.GetSession() Dim workPart As Part = theSession.Parts.Work Dim lw As ListingWindow = theSession.ListingWindow Sub Main() ' ╔════════════════════════════ CONFIG 区 (只改这里) ═══════════════════════════════╗ ' ║ [1] 两个路径 ║ ' ╚═════════════════════════════════════════════════════════════════════════════════╝ Dim csvPath As String = "D:\catalog\params.csv" ' 参数表路径 → 改为 catalog\csv\<系列>.csv Dim outDir As String = "D:\catalog\step_out\" ' STEP 输出目录 → 改为 catalog\step\ ' (目录不存在会自动创建) ' ╔═════════════════════════════════════════════════════════════════════════════════╗ ' ║ [4] STL 网格同步导出 (窗口内 3D 预览用; 不开就设 False) ║ ' ╚═════════════════════════════════════════════════════════════════════════════════╝ Dim exportStl As Boolean = True ' True = STEP 导出时同步导出同名 STL Dim stlOutDir As String = "D:\catalog\mesh\" ' STL 输出目录 → 改为 catalog\mesh\ ' ╔═════════════════════════════════════════════════════════════════════════════════╗ ' ║ [2] 尺寸映射 exprMap: "NX母模表达式名" → "CSV列名" ║ ' ║ 母模里每个独立尺寸表达式加一行; 联动尺寸(公式)不用写 ║ ' ╚═════════════════════════════════════════════════════════════════════════════════╝ Dim exprMap As New System.Collections.Generic.Dictionary(Of String, String)() exprMap.Add("bore", "bore") ' 缸径: 母模表达式 "bore" ← CSV 列 "bore" exprMap.Add("stroke", "stroke") ' 行程: 母模表达式 "stroke" ← CSV 列 "stroke" ' 示例(按需取消注释): ' exprMap.Add("magPos", "magpos") ' 磁石位置是独立规格时: CSV 要有 magpos 列 ' ╔═════════════════════════════════════════════════════════════════════════════════╗ ' ║ [3] 枚举开关映射 switchRules: 每行 = {CSV列名, 列值, NX表达式名, 表达式值} ║ ' ║ 作用: 该型号在这一列的值 = 列值 时, 把 NX 表达式设为 表达式值 ║ ' ║ (驱动母模里"按表达式抑制"的开关, 空串列值写作 "") ║ ' ╚═════════════════════════════════════════════════════════════════════════════════╝ Dim switchRules As New System.Collections.Generic.List(Of String())() switchRules.Add({"magnet", "", "magOn", "0"}) switchRules.Add({"magnet", "M", "magOn", "1"}) switchRules.Add({"mount", "", "mountIdx", "0"}) switchRules.Add({"mount", "FA", "mountIdx", "1"}) switchRules.Add({"mount", "FB", "mountIdx", "2"}) switchRules.Add({"mount", "CA", "mountIdx", "3"}) switchRules.Add({"mount", "CB", "mountIdx", "4"}) switchRules.Add({"mount", "LB", "mountIdx", "5"}) switchRules.Add({"mount", "YB", "mountIdx", "6"}) ' ================================================================ lw.Open() lw.WriteLine("批量导出开始: " & csvPath) Directory.CreateDirectory(outDir) If exportStl Then Directory.CreateDirectory(stlOutDir) lw.WriteLine("同步导出 STL 网格: " & stlOutDir) End If Dim lines() As String = File.ReadAllLines(csvPath) If lines.Length < 2 Then lw.WriteLine("参数表为空!") Return End If Dim header() As String = lines(0).Split(","c) Dim colStep As Integer = Array.IndexOf(header, "step_file") If colStep < 0 Then lw.WriteLine("参数表缺少 step_file 列!") Return End If ' 预解析列号 Dim colOf As New System.Collections.Generic.Dictionary(Of String, Integer)() For Each kv As KeyValuePair(Of String, String) In exprMap colOf(kv.Key) = Array.IndexOf(header, kv.Value) If colOf(kv.Key) < 0 Then lw.WriteLine("参数表缺少列: " & kv.Value) Return End If Next Dim okCount As Integer = 0 Dim failCount As Integer = 0 Dim skipCount As Integer = 0 ' 去重: 多个型号行共用同一 step_file, 每个文件只导出一次 (本批内) Dim exported As New System.Collections.Generic.HashSet(Of String)() For i As Integer = 1 To lines.Length - 1 If lines(i).Trim().Length = 0 Then Continue For Dim c() As String = lines(i).Split(","c) Dim model As String = c(0).Trim() Dim stepFile As String = c(colStep).Trim() If exported.Contains(stepFile) Then skipCount += 1 Continue For End If ' 断点续跑: 输出目录已存在同名文件 → 跳过 (想强制重导, 先删该文件再跑) If File.Exists(Path.Combine(outDir, stepFile)) Then exported.Add(stepFile) skipCount += 1 Continue For End If lw.Write("[" & i & "/" & (lines.Length - 1) & "] " & stepFile & " ... ") Try ' ---- 1) 设置表达式 (尺寸) ---- For Each kv As KeyValuePair(Of String, String) In exprMap workPart.Expressions.Edit(kv.Key, c(colOf(kv.Key)).Trim()) Next ' ---- 1.5) 设置枚举开关 (抑制/特征组切换) ---- For Each rule As String() In switchRules Dim colIdx As Integer = Array.IndexOf(header, rule(0)) If colIdx >= 0 AndAlso c(colIdx).Trim() = rule(1) Then workPart.Expressions.Edit(rule(2), rule(3)) End If Next ' ---- 2) 更新模型 ---- Dim update As NXOpen.Update = theSession.CreateUpdate() Dim nErrs As Integer = 0 update.InterpartDelay = False update.ModelingInterpartUpdate = True update.DoUpdate(nErrs) update.Dispose() If nErrs > 0 Then lw.WriteLine("警告: 更新有 " & nErrs & " 个错误") End If ' ---- 3) 导出 STEP ---- ExportStep(Path.Combine(outDir, stepFile)) ' ---- 3.5) 同步导出 STL 网格 (窗口内 3D 预览; 同名 .stl) ---- If exportStl Then Dim stlFile As String = Path.ChangeExtension(stepFile, ".stl") If Not File.Exists(Path.Combine(stlOutDir, stlFile)) Then ExportStl(Path.Combine(stlOutDir, stlFile)) End If End If exported.Add(stepFile) okCount += 1 lw.WriteLine("OK") Catch ex As Exception failCount += 1 lw.WriteLine("FAIL: " & ex.Message) End Try Next lw.WriteLine("") lw.WriteLine("完成: " & okCount & " 个文件导出成功, " & failCount & " 失败, " & skipCount & " 行共用文件已跳过 (共扫描 " & (lines.Length - 1) & " 行型号), 输出目录: " & outDir) End Sub ' STEP214 导出 (NX 10+ DexBuilder; 旧版本请用录制日记替换此函数) Sub ExportStep(fileName As String) Dim dexBuilder As NXOpen.DexBuilder = workPart.DexManager.CreateBuilder() dexBuilder.PartType = NXOpen.DexBuilder.PartTypeOption.Part dexBuilder.OutputFile = fileName dexBuilder.Translator = NXOpen.DexBuilder.TranslatorType.Step214 dexBuilder.ColorAndLayers = True dexBuilder.Commit() dexBuilder.Destroy() End Sub ' STL 网格导出 (窗口内 3D 预览用, 二进制格式体积小; 若 NX 版本 API 有差异, ' 用【工具→日记→录制】录一次 文件→导出→STL 替换本函数体) Sub ExportStl(fileName As String) Dim stlBuilder As NXOpen.StlBuilder = workPart.StlManager.CreateStlBuilder() stlBuilder.OutputFile = fileName stlBuilder.BinaryFormat = True ' 二进制 STL stlBuilder.TriangleTolerance = 0.5 ' 三角网格公差 (mm), 越小越精细文件越大 (0.5 屏幕预览足够) stlBuilder.AdjacentTolerance = 0.1 stlBuilder.AutoNormalGen = True stlBuilder.NormalDirection = 1 ' 1 = 朝外 stlBuilder.Commit() stlBuilder.Destroy() End Sub End Module