I have a VBA macro the reads each attachment, copies the graphical elements into an array, and writes the array of elements into the active model as a cell. (See code.) I now need to go a step further and address any elements that are clipped from the attachment. As currently written, the macro copies every graphical element, visible and clipped. Is it possible to exclude the clipped elements? In essence I am looking for a way to mimic "merge into master" but keep the attachment elements grouped.
Option Explicit Option Base 1 Sub MergeReferences() Dim nAttachments As Integer nAttachments = ActiveModelReference.Attachments.Count Dim i As Integer For i = nAttachments To 1 Step -1 If LCase(ActiveModelReference.Attachments.Item(i).AttachName) <> "sig.dgn" Then If ActiveModelReference.Attachments.Item(i).DisplayFlag = True Then Dim NewCellName As String If ActiveModelReference.Attachments.Item(i).LogicalName <> "" Then NewCellName = ActiveModelReference.Attachments.Item(i).LogicalName Else NewCellName = ActiveModelReference.Attachments.Item(i).AttachName End If Dim sc As New ElementScanCriteria sc.ExcludeNonGraphical Dim cc As New CopyContext cc.LevelHandling = msdCopyContextLevelCopyIfNotFound Dim ee As ElementEnumerator Set ee = ActiveModelReference.Attachments.Item(i).Scan(sc) Dim eleArray() As Element Dim m As Integer m = 0 While ee.MoveNext If ee.Current.Type = msdElementTypeText Then If ee.Current.AsTextElement.Text = "$DOCSET_CURRENTSETDOC$" Then ActiveModelReference.CopyElement ee.Current, cc ElseIf ee.Current.AsTextElement.Text = "$DOCSET_NUMSETDOCS$" Then ActiveModelReference.CopyElement ee.Current, cc ElseIf ee.Current.AsTextElement.Text = "INSERT$CO" Then ActiveModelReference.CopyElement ee.Current, cc Else m = m + 1 ReDim Preserve eleArray(m) Set eleArray(m) = ee.Current.Clone End If Else m = m + 1 ReDim Preserve eleArray(m) Set eleArray(m) = ee.Current.Clone End If Wend Dim eleCell As CellElement Set eleCell = CreateCellElement1(NewCellName, eleArray, Point3dFromXY(0, 0)) ActiveModelReference.AddElement eleCell ActiveModelReference.Attachments.Remove i End If End If Next i ActiveDesignFile.Views.Item(1).DisplaysTags = True End Sub
Hi Brian,
be aware this is general Developers and Programming forum, so I recommend to move your question to MicroStation Programming forum (I assume you use MicroStation). To move existing discussion to another forum, use More > Move tool, available under your original post.
Also, please read and follow the best practices, because you wrote your question, but do not share any single information about user product and its version.
With regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Brian Loughry said:Is it possible to exclude the clipped elements?
A clipped element is just an element. It has no information about its origin or whether it was created by a clipping process.
Regards, Jon Summers LA Solutions
Sorry, I did not notice a separate forum to post Microstation programming questions. Thank you for moving the discussion to the proper forum. Also, thank you for pointing out the best practices. I have updated the subject to include the Microstation release and update.
It makes sense that the element would not know it was a "clipped" element, but Microstation must. Is that clipping area accessible to VBA? One option I can think of, assuming the clipping area is known by VBA, is to test whether each element is inside or outside the clipping area. If inside, the element could be excluded from the element array. Then the question is what happens with elements that cross the clipping plane? Before I go too far down this path, is my desire of mimicking the "merge into master" command and creating a cell even possible? Possibly there is a better way of accomplishing this? I am open to any suggestions.
Brian Loughry said:One option I can think of, assuming the clipping area is known by VBA, is to test whether each element is inside or outside the clipping area
Unfortunately, VBA doesn't know about clip boundaries or masks. You have to call a function from the C++ MicroStationAPI to get an array of clip points. It's explained here, but it's not pretty.
Brian Loughry said:Possibly there is a better way of accomplishing this?
Concede defeat with VBA and use a more capable development language: either C++ or .NET.
Thank you for the explanation. When I initially typed my question, I feared that VBA may not know about clip boundaries or masks. One of these days I will learn C++ and .NET, but until then VBA is what I know.
Before conceding total defeat, I have one last thought, kind of a compromise. I could use VBA to get the attachments and then use the "REFERENCE MERGE" key-in. This would of course not keep the elements grouped, which is my preference, not necessarily the end customer's. I did look at your link for the C++ MicroStationAPI function, and yes, it is not pretty. How messy would it be to create a function that simply returned whether there is a clipping boundary or mask for each attachment? My thinking is if there are no clips, I could use the existing code and if there are clips I could use the "REFERENCE MERGE" key-in. If that seem like a viable solution, where can I find more information on creating that function?
Brian Loughry said:How messy would it be to create a function that simply returned whether there is a clipping boundary or mask for each attachment?
Unfortunately I think there is no information about attachment clipping available in VBA API at all. So it leads back to the calling proper function in native API.
Brian Loughry said:I could use VBA to get the attachments and then use the "REFERENCE MERGE" key-in.
I am not sure (and probably it does not work well too), but can be a workaround to use Save as function and to set option External attachment: Merge to Cell? The problem here is that there is probably no key-in to control Save as options.
Regards,
rather than copying elements, you can try this approach:
run keyin from vba to merge a reference with optimized clipping turn on
create a cell from the newly merged element
The tricky bit would be to identify "newly merged elements" but I'm pretty sure there're examples around for that topic.
But 1 of the issue with merging references is you lose reference specific level override settings.
Answer Verified By: Brian Loughry
Tuan Le said:The tricky bit would be to identify "newly merged elements" but I'm pretty sure there're examples around for that topic
Please be more specific: what examples show how to obtain 'newly merged elements' (a.k.a. 'newly created elements')?
For one, there's an example called "Find Dropped Cell Using IncludeOnlyFilePositionRange" in the microstation vba help file, which can be accessed via the "example" link from IncludeOnlyFilePositionRange Method entry.