Caita二次开发(VB.NET)(4)——批量提取与归档Part/Product属性数据

张开发
2026/4/19 18:27:09 15 分钟阅读

分享文章

Caita二次开发(VB.NET)(4)——批量提取与归档Part/Product属性数据
1. 为什么需要批量提取CATIA属性数据在机械设计领域CATIA是最常用的三维设计软件之一。工程师在日常工作中经常需要处理大量零部件Part和装配体Product的属性数据。这些数据可能包括零部件的基本信息图号、版本、描述等设计参数材料、重量、尺寸等自定义属性供应商、成本、设计者等手动一个个打开文件查看属性不仅效率低下而且容易出错。我曾经参与过一个汽车零部件项目需要统计2000多个零件的材料属性如果手动操作至少需要3天时间。而通过VB.NET二次开发实现的批量提取工具仅用20分钟就完成了全部数据的采集和整理。2. 开发环境准备2.1 软件要求要开发CATIA批量属性提取工具需要准备以下环境CATIA V5建议R25及以上版本Visual Studio2015或更高版本.NET Framework 4.0或更高版本CATIA Automation API引用在VS中新建VB.NET项目后需要添加对CATIA类型库的引用。具体操作是在解决方案资源管理器中右键点击引用选择添加引用在COM选项卡中找到CATIA V5 INFITF 1.0 Type Library勾选后点击确定2.2 基础代码框架我们先建立一个基础的操作框架包含以下核心功能CATIA应用程序连接文档打开/关闭错误处理机制Imports INFITF Imports System.IO Public Class CATIAAttributeExtractor Private catiaApp As INFITF.Application 连接CATIA应用程序 Private Function ConnectToCATIA() As Boolean Try catiaApp GetObject(, CATIA.Application) Return True Catch ex As Exception Console.WriteLine(无法连接到CATIA: ex.Message) Return False End Try End Function 安全打开CATIA文档 Private Function OpenCATIADocument(filePath As String) As Document Try catiaApp.DisplayFileAlerts False Dim doc As Document catiaApp.Documents.Open(filePath) Return doc Catch ex As Exception Console.WriteLine(打开文件失败: filePath) Return Nothing Finally catiaApp.DisplayFileAlerts True End Try End Function 关闭当前文档 Private Sub CloseCurrentDocument() If catiaApp.ActiveDocument IsNot Nothing Then catiaApp.ActiveDocument.Close() End If End Sub End Class3. 属性提取核心实现3.1 读取基本属性CATIA中的Part和Product都有一组标准属性我们可以通过Product对象访问这些基础信息Public Function GetBasicProperties(doc As Document) As Dictionary(Of String, String) Dim properties New Dictionary(Of String, String) If doc.Product IsNot Nothing Then properties.Add(PartNumber, doc.Product.PartNumber) properties.Add(Revision, doc.Product.Revision) properties.Add(Definition, doc.Product.Definition) properties.Add(Nomenclature, doc.Product.Nomenclature) properties.Add(Source, doc.Product.Source) properties.Add(Description, doc.Product.DescriptionRef) End If Return properties End Function在实际项目中我发现不同版本的CATIA对某些属性的支持可能不同。比如在R25中Description属性可能为空而在R28中则可以正常获取。因此建议添加适当的空值检查。3.2 提取自定义属性自定义属性是工程师在设计过程中添加的额外信息存储在UserRefProperties集合中Public Function GetCustomProperties(doc As Document) As Dictionary(Of String, String) Dim customProps New Dictionary(Of String, String) For Each prop As [Property] In doc.Product.UserRefProperties Try 过滤掉空值属性 If Not String.IsNullOrEmpty(prop.Value) Then customProps.Add(prop.Name, prop.Value.ToString()) End If Catch ex As Exception 某些特殊属性可能无法直接读取 Console.WriteLine($读取属性{prop.Name}失败: {ex.Message}) End Try Next Return customProps End Function这里有个实用技巧某些自定义属性可能是多语言或特殊格式的直接读取可能会抛出异常。因此我添加了Try-Catch块来确保程序稳定性。4. 批量处理与文件遍历4.1 递归遍历文件夹要实现批量处理我们需要能够递归扫描指定文件夹下的所有CATIA文件Public Sub ProcessFolder(folderPath As String, outputPath As String) If Not Directory.Exists(folderPath) Then Console.WriteLine(文件夹不存在: folderPath) Return End If 支持的CATIA文件扩展名 Dim supportedExtensions As String() {.CATPart, .CATProduct} 处理当前文件夹中的文件 For Each filePath As String In Directory.GetFiles(folderPath) Dim extension As String Path.GetExtension(filePath).ToLower() If supportedExtensions.Contains(extension) Then ProcessSingleFile(filePath, outputPath) End If Next 递归处理子文件夹 For Each subFolder As String In Directory.GetDirectories(folderPath) ProcessFolder(subFolder, outputPath) Next End Sub在实际应用中我建议添加文件过滤功能比如只处理特定前缀或包含特定关键字的文件。这可以通过修改GetFiles的参数来实现。4.2 多线程处理优化当处理大量文件时单线程方式可能效率较低。我们可以引入并行处理Imports System.Threading.Tasks Public Sub ProcessFolderParallel(folderPath As String, outputPath As String) Dim allFiles As New List(Of String)() GetAllCATIAFiles(folderPath, allFiles) Dim options As New ParallelOptions() options.MaxDegreeOfParallelism Environment.ProcessorCount - 1 Parallel.ForEach(allFiles, options, Sub(filePath) ProcessSingleFile(filePath, outputPath) End Sub) End Sub Private Sub GetAllCATIAFiles(folderPath As String, fileList As List(Of String)) Dim supportedExtensions As String() {.CATPart, .CATProduct} For Each filePath As String In Directory.GetFiles(folderPath) Dim extension As String Path.GetExtension(filePath).ToLower() If supportedExtensions.Contains(extension) Then fileList.Add(filePath) End If Next For Each subFolder As String In Directory.GetDirectories(folderPath) GetAllCATIAFiles(subFolder, fileList) Next End Sub需要注意的是CATIA Automation API对多线程的支持有限实际测试中发现并行度不宜设置过高否则可能导致CATIA崩溃。建议将MaxDegreeOfParallelism设置为2-4之间。5. 数据输出与格式处理5.1 Excel输出实现将提取的属性数据输出到Excel比TXT更便于后续处理Imports Microsoft.Office.Interop.Excel Public Sub ExportToExcel(data As List(Of Dictionary(Of String, String)), outputPath As String) Dim excelApp As New Application() Dim workbook As Workbook excelApp.Workbooks.Add() Dim worksheet As Worksheet CType(workbook.Sheets(1), Worksheet) 写入表头 Dim headerRow As Integer 1 Dim colIndex As Integer 1 For Each key In data(0).Keys worksheet.Cells(headerRow, colIndex) key colIndex 1 Next 写入数据 Dim rowIndex As Integer 2 For Each item In data colIndex 1 For Each value In item.Values worksheet.Cells(rowIndex, colIndex) value colIndex 1 Next rowIndex 1 Next 自动调整列宽 worksheet.Columns.AutoFit() 保存文件 workbook.SaveAs(outputPath) workbook.Close() excelApp.Quit() 释放COM对象 ReleaseObject(worksheet) ReleaseObject(workbook) ReleaseObject(excelApp) End Sub Private Sub ReleaseObject(ByVal obj As Object) Try System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) obj Nothing Catch ex As Exception obj Nothing Finally GC.Collect() End Try End Sub这里有几个关键点需要注意必须正确释放Excel COM对象否则可能导致Excel进程残留对于大量数据超过1万行建议使用EPPlus等库代替Interop添加适当的错误处理特别是文件保存时的权限检查5.2 数据库存储方案对于企业级应用将数据直接存入数据库是更好的选择Imports System.Data.SqlClient Public Sub SaveToDatabase(data As Dictionary(Of String, String), connectionString As String) Using connection As New SqlConnection(connectionString) connection.Open() Dim commandText As String INSERT INTO PartAttributes (PartNumber, Revision, [Description], AttributeName, AttributeValue) VALUES (PartNumber, Revision, Description, AttributeName, AttributeValue) Using command As New SqlCommand(commandText, connection) 添加公共参数 command.Parameters.AddWithValue(PartNumber, data(PartNumber)) command.Parameters.AddWithValue(Revision, data(Revision)) command.Parameters.AddWithValue(Description, data(Description)) 插入自定义属性 For Each item In data If Not {PartNumber, Revision, Description}.Contains(item.Key) Then command.Parameters(AttributeName).Value item.Key command.Parameters(AttributeValue).Value item.Value command.ExecuteNonQuery() End If Next End Using End Using End Sub在实际项目中我建议使用存储过程代替直接SQL语句添加事务处理确保数据完整性考虑批量插入SqlBulkCopy以提高性能6. 实用技巧与性能优化6.1 内存管理与性能调优处理大量CATIA文件时内存管理尤为重要。以下是我总结的几个经验及时释放对象每个打开的CATIA文档都会占用内存处理完后应立即关闭Dim doc As Document catiaApp.Documents.Open(filePath) ...处理文档... doc.Close() 及时关闭文档 ReleaseObject(doc) 释放COM对象禁用不必要的界面更新在处理过程中禁用CATIA的界面刷新可以显著提高性能catiaApp.RefreshDisplay False 禁用界面刷新 ...批量处理代码... catiaApp.RefreshDisplay True 恢复界面刷新分批次处理对于超大规模文件如超过5000个建议分批次处理每处理100-200个文件后重启CATIA进程6.2 错误处理与日志记录健壮的错误处理机制是自动化工具的关键Public Sub ProcessSingleFile(filePath As String, outputPath As String) Dim logger As New StringBuilder() Try logger.AppendLine($开始处理文件: {filePath}) Dim doc As Document OpenCATIADocument(filePath) If doc Is Nothing Then logger.AppendLine(文件打开失败可能已被其他进程锁定) Return End If 提取属性 Dim basicProps GetBasicProperties(doc) Dim customProps GetCustomProperties(doc) 合并属性 Dim allProps As New Dictionary(Of String, String)(basicProps) For Each item In customProps allProps.Add(item.Key, item.Value) Next 输出结果 ExportToExcel(allProps, outputPath) logger.AppendLine(文件处理成功) Catch ex As Exception logger.AppendLine($处理过程中发生错误: {ex.Message}) logger.AppendLine($堆栈跟踪: {ex.StackTrace}) Finally CloseCurrentDocument() WriteLog(logger.ToString()) End Try End Sub建议将日志记录到文件中便于后续问题排查。对于长期运行的批处理任务还可以添加邮件通知功能在任务完成或出错时发送通知。7. 扩展功能与实战案例7.1 属性对比与差异分析在版本控制场景中我们经常需要比较不同版本间的属性差异。可以扩展工具实现以下功能Public Function CompareProperties(oldProps As Dictionary(Of String, String), newProps As Dictionary(Of String, String)) As Dictionary(Of String, String()) Dim differences As New Dictionary(Of String, String()) 检查被删除的属性 For Each key In oldProps.Keys If Not newProps.ContainsKey(key) Then differences.Add(key, New String() {oldProps(key), 已删除}) End If Next 检查新增或修改的属性 For Each key In newProps.Keys If Not oldProps.ContainsKey(key) Then differences.Add(key, New String() {新增, newProps(key)}) ElseIf Not oldProps(key).Equals(newProps(key)) Then differences.Add(key, New String() {oldProps(key), newProps(key)}) End If Next Return differences End Function这个功能在以下场景特别有用设计变更管理多版本BOM对比供应商交付物检查7.2 与PDM/PLM系统集成对于使用PDM/PLM系统的企业可以将属性提取工具与系统集成Public Sub SyncWithPLM(partData As Dictionary(Of String, String), plmEndpoint As String) Dim client As New HttpClient() Dim json JsonConvert.SerializeObject(partData) Dim content New StringContent(json, Encoding.UTF8, application/json) Try Dim response client.PostAsync(plmEndpoint, content).Result If Not response.IsSuccessStatusCode Then Throw New Exception($PLM同步失败: {response.StatusCode}) End If Catch ex As Exception 实现重试逻辑 For i As Integer 1 To 3 Try Thread.Sleep(1000 * i) 指数退避 Dim retryResponse client.PostAsync(plmEndpoint, content).Result If retryResponse.IsSuccessStatusCode Then Return End If Catch retryEx As Exception 记录重试失败 End Try Next Throw 重试后仍然失败则抛出异常 End Try End Sub在实际项目中与PLM系统集成时需要考虑认证与授权机制数据加密要求网络延迟和超时设置批量操作的性能优化

更多文章