Deleting a Cell Definition to Replace the Cells with a Different One

Hi

I'm looking for help on the question detailed above where my purpose is to delete a certain SharedCellDefinition (I failed at writing a VBA snippet for this so resorted to the CadInputQueue instead), then attach a new cell library (the code firstly searches for a string to get the location of the cell library) and, lastly, replace all cells which used the previous cell definition with ones from the attached library.

I figured the way to replace the cells was to get a scan going which would find the SharedCellDefinition that I wanted to change them to, and then enumerate through all the cells I wanted to use (replace the cell defintion) but this seems to have not worked.

This is slightly more problematic as my code does not give me any errors when I run, and when I try the key-ins (even the ".SendCommand "delete scdefs KPR"" line does not seem to achieve the desired result as part of the macro), etc, by hand, the same actions result in exactly the process I want to happen, so I am slightly unsure what's going wrong. I'm hoping it is as simple as me missing out a "Redraw"/"Rewrite" from where there should be one.

Thoughts on what's going wrong?

Anyways, here's the code (I was trying to use the SyntaxHighlighted but it seems I failed in that as well -- did I need to manually highlight it there? I copied it in and chose "VB" in the options but this text editor doesn't show any changes to what I input).

Sub Main()

With CadInputQueue
        .SendCommand "delete scdefs KPR"
        CommandState.StartDefaultCommand '  Back to a standard state
    End With

    Dim alcCells As String
    alcCells = Share.GetCells
    
    AttachCellLibrary alcCells 
    
    If IsCellLibraryAttached Then
        ' Proceed
        ' We now need to replace the KPR cells with those from the imported library:
        ' All cells in the level KP_R need to be then replaced with the new imported "KPR" cell
        ' After that, the replaced cells need to be scaled down to half the size they are at.
        
        Call ReplaceCells(lvlKPR, "KPR")
        
    Else: Exit Sub
    End If

End Sub

Private Sub ReplaceCells(levelName As String, replacingElement As String)

    Dim oReplacer As SharedCellDefinitionElement
    Dim replaceScanCriteria As ElementScanCriteria
    Set replaceScanCriteria = New ElementScanCriteria
    replaceScanCriteria.ExcludeAllTypes
    replaceScanCriteria.IncludeType msdElementTypeSharedCellDefinition
    
    Dim replEnum As ElementEnumerator
    Set replEnum = ActiveModelReference.Scan(replaceScanCriteria)
    
    Do While replEnum.MoveNext
        If replEnum.Current.IsSharedCellDefinitionElement Then
            Dim tempSCE As SharedCellDefinitionElement
            Set tempSCE = replEnum.Current
            
            If tempSCE.Name = replacingElement Then
                Set oReplacer = tempSCE
                Exit Do
            End If
        End If
    Loop
    
    ' Set up corresponding level object
    Dim oLevel As Level
    Set oLevel = ActiveDesignFile.Levels(levelName)

    ' Set up scan criteria
    Dim oScanCriteria As ElementScanCriteria
    Set oScanCriteria = New ElementScanCriteria
    
    oScanCriteria.ExcludeAllLevels
    oScanCriteria.ExcludeAllTypes
    
    oScanCriteria.IncludeLevel oLevel
    oScanCriteria.IncludeType msdElementTypeLineString
    
    Dim oEnumerator As ElementEnumerator
    Set oEnumerator = ActiveModelReference.Scan(oScanCriteria)
    
    Dim oElement As Element
    
    Do While oEnumerator.MoveNext
        Set oElement = oEnumerator.Current
        
        If oElement.IsCellElement Then
            Dim eleCell As CellElement
            Set eleCell = oElement
            
            eleCell.ReplaceCurrentElement oReplacer
            
            eleCell.Redraw
            eleCell.Rewrite

        Else: MsgBox "This element is not suitable for this action."
        End If
    Loop
    
End Sub
  • Hi Koit,

    I did not think too much about your code, because in my opinion there is a problem in your original assumption.

    I never have not thought too much how shared cells replacement works, but I guess it's not as simple as graphic cells replacement.

    Unknown said:
    I failed at writing a VBA snippet for this so resorted to the CadInputQueue instead

    Based on MicroStation VBA help file the key-in syntax is: DELETE SCDEFS <ALL | ANONYMOUS | NAMED>.  Based on what information you use the key-in delete scdefs KPR?

    Unknown said:
    my purpose is to delete a certain SharedCellDefinition ... then attach a new cell library (the code firstly searches for a string to get the location of the cell library) and, lastly, replace all cells which used the previous cell definition with ones from the attached library.

    How do you want to delete Shared Cell Definition element (step 1) if there are the shared cells instances and to replace the instances later (step 3)? It cannot work. The I have not tried do it using VBA or MDL code, but I am pretty sure the Shared Cell Defintion can be removed only if there are no instances linked to it the definition. It's what a compress option "SC_NAMED" and the key-in DELETE SCDEFS ALL do.

    Unknown said:
    and when I try the key-ins (even the ".SendCommand "delete scdefs KPR"" line does not seem to achieve the desired result

    What is your desired result using this key-in? The key-in itself is wrongly used I guess and it's not clear why you want to delete the shared cell definition element in the situation it's still used by some shared cells.

    Unknown said:
    I was trying to use the SyntaxHighlighted but it seems I failed in that as well

    SyntaxHighlighter tool works fine. Did you set in the tool that your code is VB code? Otherwise the code is usually not highlighted because identified as a normel text.

    Unknown said:
    Thoughts on what's going wrong?

    Well ... see my comments. But I am thinking it your first wrong step is why you don't use MicroStation cell replacement tool that works I guess fine and can be easily used to replace all instances of one shared cell by another shared cell definition. The only requirement is the cells have to have the same name.

    With regards,

      Jan

  • Jan,

    Thanks for the prompt reply.

    I noticed the highlighter worked after posting; I just thought it would be noticeable in the text editor as well so when it wasn't I had the thought that something was wrong... Seems to be alright though.

    I should have clarified. "KPR" is the name of the cell model I am deleting. Therefore, the way I figured it would work is that the definition "NAMED" would be replaced by the specific cell name in this instance?

    I found no reference to the cell replacement tool in the Microstation v8 VBA Help other than the ReplaceCurrentElement which is the one I was trying to use -- but you seem to be referring to something else?

    The new cell has the same name as the old one -- thinking about it right now, there does not seem to be any need to delete the cell definition but that was the way it was originally suggested I work. Going through the process right now in the program, it worked exactly the same without deleting the original model so I don't think there is an actual need to delete it. I guess that bit can be scrapped.

    I'm still curious by the ReplaceCurrentElement bit though.

    Cheers
    Koit
  • Hi Koit,

    Unknown said:
    Seems to be alright though.

    Unfortunately it's not. But it shoud be possible to edit your existing post and to change the highlighter setting for the posted code.

    Unknown said:
    I found no reference to the cell replacement tool in the Microstation v8 VBA Help

    I did not write about VBA tool, but about MicroStation tool that is designed to replace both types of cells in different modes. It can be simply used by key-in, which in general I don't recommend (to use key-ins in VBA or MDL code), but in this situation it can be efficient workaround how to use existing complex functionality.

    Unknown said:
    I'm still curious by the ReplaceCurrentElement bit though.

    It's probably the method I recommend to start with. I don't know if it's possible, but if this method is able to replace SharedCellDefinition element and don't break existing connection to existing SharedCell elements (shared cells instances), it should be simple solution of your requirement.

    With regards,

      Jan

  • Thanks Jan, got it now. Seems I had to delete the original code and re-copy it. Looks better though!

    I see re the cell replacer tool.

    How about the supposition that we ignore the bit in my code where I try to delete as a SharedCellDefinition -- as you pointed out, it's both wrong and unnecessary. However, even without that, and looking specifically into the bit here (the method for replacing cells).

    Then when we consider the functionality of the ReplaceCurrentElement which you suggested I use, the function above should achieve the intended purpose. It is my understanding that I need to "find"/"retrieve" the SharedCellDefinition first before I can use it as a replacement element, which I thought this code would do. However, there is no apparent result for the above method. And note, here we are already talking about replacing CellElements/SharedCellElements and not their definitions.

    What do you think?

    Cheers

    Koit

    Private Sub ReplaceCells(levelName As String, replacingElement As String)
     
        Dim oReplacer As SharedCellDefinitionElement
        Dim replaceScanCriteria As ElementScanCriteria
        Set replaceScanCriteria = New ElementScanCriteria
        replaceScanCriteria.ExcludeAllTypes
        replaceScanCriteria.IncludeType msdElementTypeSharedCellDefinition
         
        Dim replEnum As ElementEnumerator
        Set replEnum = ActiveModelReference.Scan(replaceScanCriteria)
         
        Do While replEnum.MoveNext
            If replEnum.Current.IsSharedCellDefinitionElement Then
                Dim tempSCE As SharedCellDefinitionElement
                Set tempSCE = replEnum.Current
                 
                If tempSCE.Name = replacingElement Then
                    Set oReplacer = tempSCE
                    Exit Do
                End If
            End If
        Loop
         
        ' Set up corresponding level object
        Dim oLevel As Level
        Set oLevel = ActiveDesignFile.Levels(levelName)
     
        ' Set up scan criteria
        Dim oScanCriteria As ElementScanCriteria
        Set oScanCriteria = New ElementScanCriteria
         
        oScanCriteria.ExcludeAllLevels
        oScanCriteria.ExcludeAllTypes
         
        oScanCriteria.IncludeLevel oLevel
        oScanCriteria.IncludeType msdElementTypeLineString
         
        Dim oEnumerator As ElementEnumerator
        Set oEnumerator = ActiveModelReference.Scan(oScanCriteria)
         
        Dim oElement As Element
         
        Do While oEnumerator.MoveNext
            Set oElement = oEnumerator.Current
             
            If oElement.IsCellElement Then
                Dim eleCell As CellElement
                Set eleCell = oElement
                 
                eleCell.ReplaceCurrentElement oReplacer
                 
                eleCell.Redraw
                eleCell.Rewrite
     
            Else: MsgBox "This element is not suitable for this action."
            End If
        Loop
         
    End Sub


  • Unknown said:
    What do you think?

    Well ... nothing. This discussion is very theoretical. You have not provided any testing case and my feeling is that even basic requirements are not clearly defined. To discuss a code without having test case and exact report what is (not) working seems to me like time wasting.

    In my opinion you should at first clearly define what do you want to achieve and what requirements and condition exist, using other words "What the replacement means to you?" E.g. is there any mslink, user data or other data attached to your shared cell? To replace the cell and to maintain this extra data is substantially more complex than to work with plain cells. Also, does replacement has to maintain element id or the original element can be deleted and a new one placed?

    With regards,

      Jan