ARTICLE · 1319060
iLogic + Excel:数据驱动建模
Inventor 二次开发入门系列 · 第 17 篇
开篇:参数表该放哪里
做参数化产品时,你迟早要回答一个问题:规格参数表放哪里。
可选方案有三个: 1. 放在 iLogic 规则代码里——简单,但改规格要改代码,非技术人员无法维护 2. 放在模型参数表——只能存数值,无法存"规格名→尺寸映射" 3. 放在 Excel 表里——最灵活,业务人员能直接改,iLogic 读取
显然第三种是生产环境的标准做法。iLogic 内置了 GoExcel 对象,专门处理 Inventor 与 Excel 之间的数据交互。
本篇讲透 GoExcel 的核心用法:打开文件、按条件查行、读写单元格、数据驱动建模,以及从外部程序调用 GoExcel 的进阶技巧。
一、GoExcel 能做什么
GoExcel 是 iLogic 封装的 Excel 操作对象,底层调用的是 Excel COM API。它提供这些核心功能:
GoExcel.Open | ||
GoExcel.FindRow | ||
GoExcel.CurrentRowValue | ||
GoExcel.CellValue | ||
GoExcel.ColumnName |
相比直接用 Excel COM API,GoExcel 的优势是代码量少 70%,且自动处理 Excel 进程的启动和关闭。
二、基础用法:打开 + 查行 + 读值
假设有一个 Excel 规格表 C:\Data\parts.xlsx:
需求:根据用户输入的直径和长度,查到对应的零件号和材料,填到模型参数和 iProperties 里。
' 打开 Excel 文件和工作表GoExcel.Open("C:\Data\parts.xlsx", "Sheet1")' 多条件查找:直径=10 且 长度=50Dim rowNum As Integer = GoExcel.FindRow( _"C:\Data\parts.xlsx", _"Sheet1", _"直径", "=", 10, _ ' 第一个条件"长度", "=", 50) ' 第二个条件If rowNum > 0 Then' 找到了,读取该行的其他列Dim partNumber As String = GoExcel.CurrentRowValue("零件号")Dim material As String = GoExcel.CurrentRowValue("材料")' 填到模型里Parameter("Dia") = 10Parameter("Length") = 50iProperties.Value("Project", "Part Number") = partNumberiProperties.Value("Project", "Material") = materialInventorVb.DocumentUpdate()MessageBox.Show("已加载: " & partNumber & " / " & material, "完成")ElseMessageBox.Show("未找到匹配的规格", "提示")End If
关键点: - FindRow 的参数是成对出现的:列名 + 操作符 + 值 - 操作符支持 =, <, >, <=, >=, <> - CurrentRowValue 只在 FindRow 成功后有效,读取的是刚刚匹配到的那行 - FindRow 返回 0 或负数表示没找到。
三、FindRow 的坑:TitleRow 和 FindRowStart
GoExcel 默认假设你的 Excel 表是这样布局的:
第 1 行:可能有些标题或说明
第 2 行:列头("零件号""直径"等)
第 3 行起:数据
如果你的表不是这个布局,FindRow 会报 "Could not match the column title" 错误。
这时候需要手动设置两个属性:
- TitleRow:列头所在行号
- FindRowStart:数据起始行号(通常是 TitleRow + 1)
GoExcel.Open("C:\Data\parts.xlsx", "Sheet1")' 假设你的表:第 3 行是列头,第 4 行起是数据GoExcel.TitleRow = 3GoExcel.FindRowStart = 4' 现在就能正常查了Dim rowNum As Integer = GoExcel.FindRow( _"C:\Data\parts.xlsx", "Sheet1", "直径", "=", 10)MessageBox.Show("找到行号: " & rowNum.ToString())
避坑提醒: - 光设 FindRowStart 不够,TitleRow 也必须设对,否则列名匹配失败 - 如果你的脚本会动态改 TitleRow 多次,每次改完都要重新设 FindRowStart——它不会自动跟着 TitleRow 变 - 默认值是 TitleRow = 2,FindRowStart = 2(注意默认 FindRowStart 不是 TitleRow+1)
四、数据驱动建模的完整闭环
把前面学的串起来,做一个完整的"选规格 → 更新模型"流程。
1. Excel 规格表
2. iLogic 规则
' 配置规则:让用户选规格Sub Main()' 读取 Excel 里的所有规格名GoExcel.Open("C:\Data\specs.xlsx", "Sheet1")Dim specs As New ArrayListDim row As Integer = 2 ' 数据从第 2 行开始DoDim name As String = GoExcel.CellValue("A" & row)If String.IsNullOrEmpty(name) Then Exit Dospecs.Add(name)row += 1Loop' 弹窗让用户选Dim selected As String = InputListBox( _"请选择规格:", specs, specs(0), "规格选择", "iLogic Config")If String.IsNullOrEmpty(selected) Then Exit Sub' 查到对应行,读所有尺寸Dim rowNum As Integer = GoExcel.FindRow( _"C:\Data\specs.xlsx", "Sheet1", "规格", "=", selected)If rowNum <= 0 ThenMessageBox.Show("未找到规格: " & selected, "错误")Exit SubEnd If' 读取并更新模型参数Parameter("Width") = GoExcel.CurrentRowValue("Width")Parameter("Height") = GoExcel.CurrentRowValue("Height")Parameter("Depth") = GoExcel.CurrentRowValue("Depth")iProperties.Value("Project", "Part Number") = _GoExcel.CurrentRowValue("PartNumber")' 触发模型更新iLogicVb.UpdateWhenDone = TrueLogger.Info("已切换到规格: " & selected)End Sub
3. 挂到事件触发器
把这条规则挂到"New Document"事件,用户每次新建文档时就会弹窗选规格,选完自动更新模型。
这个闭环的价值:业务人员改 Excel 表加规格,不需要碰 Inventor;设计师只需选规格,不用手动改尺寸。真正的"数据驱动设计"。
五、写单元格:把模型数据导回 Excel
GoExcel 不只能读,也能写。常见场景:自动导出驱动尺寸的值到 Excel,做设计记录。
' 把当前模型的关键尺寸写到 Excel 记录表GoExcel.Open("C:\Data\DesignLog.xlsx", "Sheet1")' 找到下一个空行Dim nextRow As Integer = 2Do While Not String.IsNullOrEmpty(GoExcel.CellValue("A" & nextRow))nextRow += 1Loop' 写入本次设计的参数GoExcel.CellValue("A" & nextRow) = DateTime.Now.ToString("yyyy-MM-dd")GoExcel.CellValue("B" & nextRow) = iProperties.Value("Project", "Part Number")GoExcel.CellValue("C" & nextRow) = Parameter("Width")GoExcel.CellValue("D" & nextRow) = Parameter("Height")GoExcel.CellValue("E" & nextRow) = Parameter("Depth")' 保存 ExcelGoExcel.SaveGoExcel.Close
把这个规则挂到"After Save Document"事件,每次保存 Inventor 文档时自动追加一条设计记录。
六、进阶:从外部程序调用 GoExcel
GoExcel 是 iLogic 专属对象,在 .NET Add-In 或独立 exe 里不能直接用。但有个变通方案:把 GoExcel 调用封装成带参数的外部规则。
1. 写一个带参数的外部规则
保存为 C:\iLogic\ExcelLookup.iLogicVb:
' 通过 RuleArguments 接收参数,返回结果也通过 RuleArgumentsDim filePath As String = RuleArguments("FilePath")Dim sheetName As String = RuleArguments("Sheet")Dim dia As Double = RuleArguments("Dia")Dim length As Double = RuleArguments("Length")' 用 GoExcel 查行Dim rowNum As Integer = GoExcel.FindRow( _filePath, sheetName, "Dia", "=", dia, "Length", "=", length)If rowNum > 0 Then' 把结果塞回 RuleArguments,供调用方读取Dim outputs As NameValueMap = _ThisServer.TransientObjects.CreateNameValueMap()outputs.Add("PartNumber", GoExcel.CurrentRowValue("PartNumber"))RuleArguments.Arguments.Add("Outputs", outputs)End If
2. 从 .NET 程序调用这个外部规则
' 在 VB.NET Add-In 或 exe 里Public Sub LookupPartNumber()' m_app 是 Inventor.Application 实例Dim arguments As NameValueMap = _m_app.TransientObjects.CreateNameValueMap()arguments.Add("FilePath", "C:\Data\parts.xlsx")arguments.Add("Sheet", "Sheet1")arguments.Add("Dia", 10)arguments.Add("Length", 50)Dim doc As Document = m_app.ActiveDocumentDim externalRulePath As String = "C:\iLogic\ExcelLookup.iLogicVb"' 获取 iLogic 自动化对象Dim iLogicAuto As Object = GetiLogicAutomation(m_app)' 运行带参数的外部规则iLogicAuto.RunExternalRuleWithArguments(doc, externalRulePath, arguments)' 读取返回的结果Dim outputs As NameValueMap = NothingTryoutputs = arguments.Value("Outputs")If outputs IsNot Nothing ThenDim partNumber As String = outputs.Value("PartNumber")MessageBox.Show("零件号: " & partNumber, "结果")End IfCatch ex As ExceptionMessageBox.Show("查询失败: " & ex.Message, "错误")End TryEnd Sub' 获取 iLogic Add-In 的 Automation 对象Function GetiLogicAutomation(app As Inventor.Application) As ObjectDim addIn As Inventor.ApplicationAddIn = NothingTry' iLogic Add-In 的固定 GUIDaddIn = app.ApplicationAddIns.ItemById( _"{3BDD8D79-2179-4B11-8A5A-257B1C0263AC}")CatchReturn NothingEnd TryReturn addIn.AutomationEnd Function
这种"外部规则当桥"的思路,可以用来从 .NET 间接调用任何 iLogic 专属函数(GoExcel、GoExcel.CurrentRowValue 等)。
七、直接用 Excel COM API(替代方案)
GoExcel 有局限:它封装的是常用操作,复杂 Excel 处理(比如多表联动、公式计算、条件格式)做不了。
这时可以绕过 GoExcel,直接用 Excel COM API。iLogic 底层也是这么干的:
' 直接操作 Excel COM 对象Dim xlApp As ObjectxlApp = CreateObject("Excel.Application")xlApp.Visible = False ' 后台运行Dim xlBook As Object = xlApp.Workbooks.Open("C:\Data\parts.xlsx")Dim xlSheet As Object = xlBook.Sheets("Sheet1")' 读取单元格Dim val As String = xlSheet.Range("B2").Value' 写入单元格xlSheet.Range("B2").Value = "新值"' 遍历行Dim row As Integer = 2Do Until String.IsNullOrEmpty(xlSheet.Range("A" & row).Value)Logger.Info("行" & row & ": " & xlSheet.Range("A" & row).Value)row += 1Loop' 保存并关闭xlBook.Save()xlBook.Close()xlApp.Quit()' 释放 COM 对象(重要!)System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet)System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook)System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)
注意:直接用 COM API 必须手动释放对象,否则 Excel 进程会残留。GoExcel 帮你处理了这些,但代价是灵活性降低。
八、实战要点
1. Excel 表的列头要规范。不要用"直径(mm)"这种带括号的列名,FindRow 匹配时容易出问题,用纯英文或简短中文。
2. 大表用 FindRow,小表可以遍历。几十行的表遍历也快,几千行的表一定要用 FindRow,它内部有优化。
3. Excel 文件路径用绝对路径或相对文档路径。ThisDoc.Path & "\Data\parts.xlsx" 比 C:\... 更可移植。
4. 写完 Excel 一定要 Save + Close。GoExcel 的 GoExcel.Save 和 GoExcel.Close,或者 COM 方式的 xlBook.Save() + xlApp.Quit(),漏一步就会留僵尸进程。
5. 并发访问要小心。多个用户同时改一个 Excel 文件会冲突。多人协作场景考虑用 Vault 或数据库替代 Excel。
6. FindRowStart 坑。如果你的脚本动态修改 TitleRow 多次,FindRowStart 不会自动跟着变,必须每次显式设置。
小结
下篇预告:《iLogic 调用 VBA 和 .NET 代码》——iLogic 规则跑到复杂逻辑就力不从心?我们讲清楚 iLogic 调用 VBA 宏、引用 .NET DLL、从外部程序反向调用 iLogic 规则的完整方案。
素材来源:Autodesk Developer Blog - Use GoExcel outside a rule (Adam Nagy, 2015)、How to use GoExcel.FindRowStart (Xiaodong Liang, 2013)、Auto export driven dimension value to Excel (Adam Nagy)。















































































