Hello, I am having trouble with this code to set my level object (runtime error '5')I put here a snippet of the code:
Private Function GetFolio(ops As String) Dim elEnum As ElementEnumerator Dim el As Element Dim elScanCriteria As ElementScanCriteria Dim elLevel() As Level ReDim elLevel(UBound(OptionVB_CadreDecoupe)) For i = 0 To UBound(OptionVB_CadreDecoupe) Set elLevel(i) = ActiveDesignFile.Levels(OptionVB_CadreDecoupe(i)) Next
The error occurs on line 9.
And I put a capture of the spy tools :
any idea what I did wrong?
Hi Etienne,
what exactly do you want to achieve?
To iterate levels is rarely useful and other ways can be used (but it requires to know what your aim is).
With regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
One more comment:
It's not recommended to use "index" to access levels, because it's just a position of level in a list, starting from 1 ... which is the reason why your code crashes.
As written in MicroStation VBA help, when you really need to iterate all levels, use foreach loop.
Etienne Duperey said: I am having trouble with this code For i = 0 To UBound(OptionVB_CadreDecoupe)
For i = 0 To UBound(OptionVB_CadreDecoupe)
A perennial problem with VBA is array indices: do they start at 0 or 1? Does an array end at N or N-1? See the Option Base { 0 | 1 } directive.
Option Base { 0 | 1 }
ReDim elLevel(UBound(OptionVB_CadreDecoupe))
Your ReDim statement by default sets the lower bound of the array to the current Option Base value.
ReDim
Option Base
You are attempting to get a level whose name is CADRE_A3. Does that level exist?
CADRE_A3
Jan Šlegr said:when you really need to iterate all levels, use foreach loop
Follow Jan's advice. If you look at VBA help, it does not recommend indexing levels with an integer, but with the level name: Levels supports the standard collection interface, so it is possible to step through the collection using the For Each statement. It is also possible to retrieve a Level by indexing into the Levels collection with the level's name.
Dim oFurnitureLevel As Level Set oFurnitureLevel = ActiveDesignFile.Levels("Furniture")
Regards, Jon Summers LA Solutions
Hi Jan,
I try to retrieve a list of element according to the level, in order to know for example their position, their length or for example if an element of level 1 intersects with an element of level 2.
Etienne Duperey said:I try to retrieve a list of element according to the level
In such case, why to iterate all levels in active DGN file?
Etienne Duperey said:if an element of level 1 intersects with an element of level 2.
It's about to obtain level object(s) based on their name(s). No iteration of all levels is necessary.
Regards,
Hi Jon,
the index starts at 0 and ends at N-1.
yes the CADRE_A3 does exist, but not in the active Dgn, the latter is in a Dgn referenced in the active Dgn.
I do not understand the rest, I do not want to index a level with an integer but by its name.I will take a closer look at the documentation on this subject.
If in doubt I will add the end of my function :
Set elScanCriteria = New ElementScanCriteria elScanCriteria.ExcludeAllLevels 'Défini les critéres For i = 0 To UBound(elLevel) elScanCriteria.IncludeLevel elLevel(i) 'du scan a faire Next Set elEnum = ActiveModelReference.Scan(elScanCriteria) Do While elEnum.MoveNext res = GetLinkedElement(elEnum.Current) Loop If ops = "ID" Then End If GetFolio = elEnum.Clone.BuildArrayFromContents 'Renvoie un tableau du résultat End Function
Etienne Duperey said:yes the CADRE_A3 does exist, but not in the active Dgn, the latter is in a Dgn referenced in the active Dgn.
If you want to access elements in a reference, it's not possible to use ActiveModelReference.Scan, but to scan proper ModelReference.
Etienne Duperey said:I do not want to index a level with an integer but by its name.
In such case, just access existing level list using the level name. But be aware you have to use the right ModelReference.
Etienne Duperey said:If in doubt I will add the end of my function :
I see several problems in the code you shared (but it's not complete, so maybe I am wrong):
Etienne Duperey said:I will take a closer look at the documentation on this subject.
You really should to do it. There are plenty of code snippets available in MicroStation VBA help, and also some mvba examples (files) are delivered with MicroStation installation.
Etienne Duperey said: the CADRE_A3 does exist, but not in the active Dgn, the latter is in a Dgn referenced
If you want to build a list of lines on a particular level in all reference attachments, then you need to enumerate those models. In each model, search for lines on that level.
Write a function that creates your scan criteria for a model...
Function ScanCriteriaForLinesOnLevel (ByVal levelName As String, ByVal oModel As ModelReference) As ScanCriteria Dim oLevel As Level Set oLevel = oModel.Levels (levelName) If oLevel Is Nothing Then Debug.Print "Level '" & levelName & "' does not exist in model '" & oModel.Name & "'" Exit Function End If Dim oCriteria As New ElementScanCriteria oCriteria.ExcludeAllLevels oCriteria.IncludeLevel oLevel oCriteria.ExcludeAllTypes oCriteria.IncludeType msdElementTypeLine oCriteria.IncludeType msdElementTypeLineString Set ScanCriteriaForLinesOnLevel = oCriteria End Function
Now get a list of lines from a model...
Function GetLinesOnLevel (ByVal levelName As String, ByVal oModel As ModelReference) As Element() Dim oLines As ElementEnumerator Set oLines = oModel.Scan (ScanCriteriaForLinesOnLevel (levelName, oModel) GetLinesOnLevel = oLines.BuildArrayFromContents() End Function
Now enumerate the active model and its attachments...
Dim oLines() As Element oLines = GetLinesOnLevel (levelName, ActiveModelReference) Dim oModel As ModelRefernce For Each oModel In ActiveModelReference.Attachments oLines = GetLinesOnLevel (levelName, oModel) Next oModel