上篇我们谈到一些场景。本篇我们先来看看VBA编程可以优化的方面。大家熟悉的,VBA里有个缺省的对象ThisApplication,它是Inventor API的顶层入口。用起来比较方便,但其实会有所消耗,以下面的代码为例,它访问Locale属性10万次,花费了74.8 秒(进程外的话)。
Public Sub CallCost()
Dim timer As New clsTimer
timer.Start
Dim i As Long
For i = 1 To 100000
Dim code As Long
code = ThisApplication.Locale
Next
Debug.Print "Total time: " & Format(timer.GetTime, "0.00000")
End Sub
Public Sub CallCost()
Dim timer As New clsTimer
timer.Start
<span style="background-color: rgb(255, 255, 102);">Dim app As Inventor.Application</span>
<span style="background-color: rgb(255, 255, 51);">Set app = ThisApplication</span>
Dim i As Long
For i = 1 To 100000
Dim code As Long
code = <span style="background-color: rgb(255, 255, 51);">app.Locale</span>
Next
Debug.Print "Total time: " & Format(timer.GetTime, "0.00000")
End Sub
引用而非内联函数调用
再来一个优化,和前面类似,就是当您需要频繁调用某个对象时,尽量引用。这里有段代码遍历装配体的所有部件,获取其名字和对应的文件名。一个有500个部件的装配,循环调用10次,大约花了22.5秒。
Public Sub GetOccurrences1()
Dim asmDoc As AssemblyDocument
Set asmDoc = ThisApplication.ActiveDocument
Dim i As Integer
For i = 1 To asmDoc.ComponentDefinition.Occurrences.Count
Dim Name As String
Name = asmDoc.ComponentDefinition.Occurrences.Item(i).Name
Dim filename As String
filename = asmDoc.ComponentDefinition.Occurrences.Item(i). _
ReferencedDocumentDescriptor. _
ReferencedFileDescriptor.FullFileName
Next
End Sub
让我们稍作改动如下, 时间减少到9.7秒。
Public Sub GetOccurrences2()
Dim asmDoc As AssemblyDocument
Set asmDoc = ThisApplication.ActiveDocument
<span style="background-color: rgb(255, 255, 51);">Dim occs As ComponentOccurrences </span>
<span style="background-color: rgb(255, 255, 51);">Set occs = asmDoc.ComponentDefinition.Occurrences</span>
Dim i As Integer
For i = 1 To occs.Count
Dim Occ As ComponentOccurrence
Set Occ = occs.Item(i)
Dim Name As String
Name = Occ.Name
Dim filename As String
<span style="background-color: rgb(255, 255, 51);">filename = Occ.ReferencedDocumentDescriptor. _
ReferencedFileDescriptor.FullFileName</span>
Next
End Sub
使用For Each而不要Count 和Item
还是以便利装配中的部件为例,以下代码将花费9.4秒。虽然比前面并未有明显改变,但不同的集合会有不同的时间优化。而且,也比count item好阅读些,对吧。背后的故事是因为使用For Each的时候,Inventor提前知道您讲遍历一个集合,就会先从内部优化。而count item的模式,Inventor不知您是遍历一次呢,还是多次呢,还是整个集合,所以提前不会做什么优化工作。
Public Sub GetOccurrences3()
Dim asmDoc As AssemblyDocument
Set asmDoc = ThisApplication.ActiveDocument
Dim occs As ComponentOccurrences
Set occs = asmDoc.ComponentDefinition.Occurrences
Dim Occ As ComponentOccurrence
<span style="background-color: rgb(255, 255, 51);"> For Each Occ In occs </span>
Dim Name As String
Name = Occ.Name
Dim filename As String
filename = Occ.ReferencedDocumentDescriptor. _
ReferencedFileDescriptor.FullFileName
Next
End Sub
通过名字过去某条目Item
和集合关联的另外一种优化就是,假设要获取集合内某个对象条目,尽量用名字获取,而不要遍历一个个查找。例如,这段代码想获得某个TranslatorAddIn.
Dim dxfAddIn As TranslatorAddIn
For i = 1 To addIns.Count
If addIns(i).AddInType = kTranslationApplicationAddIn Then
Dim desc As String
desc = addIns(i).Description
If desc = "Autodesk Internal DXF Translator" Then
Set dxfAddIn = addIns.Item(i)
Exit For
End If
End If
Next
而下面这段代码,不仅效率提高,而且也美观些。
Dim dxfAddIn As TranslatorAddIn
Set dxfAddIn = addIns. _
ItemById("{C24E3AC4-122E-11D5-8E91-0010B541CD80}")