Тема: Как удалить блок из VBA

Никак не удается удалить программно блок.
Все время выдается ошибка, что имеется ссылка на блок. Использовал многие советы с данного форума: удалял все содержимое из блока, пыталс удалить командой из командной строки. Ничего не получилось

Re: Как удалить блок из VBA

Если есть другие блоки, в состав которых входит тот, который вы хотите удалить, то те блоки и не дают его удалить. Они на него ссылаются (через Item(1),Item(2),...) . Как прикажите разрушать эти другие блоки. Можно их удалить. Если вам эти другие блоки не жалко, а также не жалко и те "более другие", которые ссылаются на другие и т.д., то лучше всего сделать рекурсивную функцию которая итерирует по коллекция ThisDrawing.Blocks и ThisDrawing.ModelSpace и удаляет блоки начиная с самых всеохватывающих.

Re: Как удалить блок из VBA

лучше всего сделать рекурсивную функцию которая итерирует по коллекция ThisDrawing.Blocks и ThisDrawing.ModelSpace и удаляет блоки начиная с самых всеохватывающих.

Или удаляет "ненужный" блок из описания всех имеющихся в чертеже блоков.

Re: Как удалить блок из VBA

Если блок для определенности BlockA используется в построении других блоков BlockB,BlockC, ..., то можно поступить как минимум трояко.
0 - (по умолчанию) удаляется все, т.е. BlockA, BlockB, BlockC, и т.д., включая блоки, ссылающиеся на BlockB,...
1 - удаляется BlockA, при этом все блоки которые непосредственно ссылаются на BlockA не удаляются, а корректируются, в этих блоках удаляются ссылки на BlockA
2 - BlockA удаляется тогда и только тогда, когда он не используется в конструкциях других блоков.
Вот набросал

Option Explicit
Sub test()
    'ThisDrawing.Regen acActiveViewport
    MsgBox "Из ""ThisDrawing.Blocks"" удалено блоков: " & DeleteBlock("testBlock")
    ThisDrawing.Regen acActiveViewport
End Sub
Public Function DeleteBlock(Optional ByVal blockToDeleteName As String = "!", _
                            Optional ByVal referencedBlock As Integer = 0) As Integer
' формирует глобальный массив sBlocksToDeleteArray() блоков подлежащих удалению
' возрващает 0, если данное имя не сущетвует
' возрващает N>0, число блоков удаленных из ThisDrawing.Blocks
' referencedBlock = 0, удаляеются все референсные блоки
'                 = 1, из референсных блоков удаляются ссылки на блок с именем blockToDeleteName
'                 = 2, если есть референсные блоки, то блок с именем blockToDeleteName не удаляется
    Static ub As Integer
    Static blocksTotal As Integer
    Static sBlockNames() As String
    Static iBlockNames() As Integer
    Static iBlocksToDeleteArray() As Integer
    Dim acBlock As AcadBlock
    Dim acBlockName As String
    Dim acBlockRef As AcadBlockReference
    Dim iBlocksDeleted As Integer
    Dim i As Integer
    Dim j As Integer
    Dim k As Integer
    Dim entry As AcadEntity
    Dim nameExists As Boolean
    Dim delBlock As Boolean
    Static i1 As Integer
    Dim itemsTotal As Integer
    Dim retValue As Integer
    ' если первый аргумент не равен "!"
    If blockToDeleteName <> "!" Then
        ' формируем массив блоков
        blocksTotal = 0
        For Each acBlock In ThisDrawing.Blocks
            acBlockName = acBlock.Name
            If Not (acBlockName Like "*Model_Space") And Not (acBlockName Like "*Paper_Space*") Then
                blocksTotal = blocksTotal + 1
                ReDim Preserve sBlockNames(1 To blocksTotal)
                sBlockNames(blocksTotal) = acBlockName
            End If
        Next
        nameExists = False
        For i = 1 To blocksTotal
            If sBlockNames(i) = blockToDeleteName Then
                nameExists = True
                Exit For
            End If
        Next
        If nameExists = False Then  ' блок с таким именем не существует
            DeleteBlock = 0
            Exit Function
        End If
        ub = 1
        ReDim iBlocksToDeleteArray(1 To 1) ' формируем массив номеров блоков, которые будут удаляться
        iBlocksToDeleteArray(1) = i
        i1 = 1
        retValue = DeleteBlock("!", referencedBlock)
        If retValue = -2 Then
            DeleteBlock = 0
            Exit Function
        ElseIf referencedBlock = 1 Then
            ub = 1
        End If
        ' удаление вставок блоков с пространсва модели в обратном порядке
        iBlocksDeleted = 0
        For i = ub To 1 Step -1
            acBlockName = sBlockNames(iBlocksToDeleteArray(i))
            For Each entry In ThisDrawing.ModelSpace
                If entry.ObjectName = "AcDbBlockReference" Then
                    Set acBlockRef = entry
                    If acBlockRef.EffectiveName = acBlockName Then
                        acBlockRef.Delete
                    End If
                End If
            Next
            On Error Resume Next
            ThisDrawing.Blocks.Item(acBlockName).Delete
            If Err = 0 Then iBlocksDeleted = iBlocksDeleted + 1
            On Error GoTo 0
        Next
        DeleteBlock = iBlocksDeleted
        Exit Function
    End If
    ' если первый аргумент равен "!"
    If blockToDeleteName <> "!" Then i1 = 1
    Do
        For i = i1 To ub
            ' пополняем массив iBlocksToDeleteArray()
            acBlockName = sBlockNames(iBlocksToDeleteArray(i))
            For j = 1 To blocksTotal
                If j <> iBlocksToDeleteArray(i) Then
                    ' проверяем, если среди Items блока j ссылки на i
                    Set acBlock = ThisDrawing.Blocks.Item(sBlockNames(j))
                    itemsTotal = acBlock.Count
                    For k = itemsTotal - 1 To 0 Step -1
                        Set entry = acBlock.Item(k)
                        If entry.ObjectName = "AcDbBlockReference" Then
                            Set acBlockRef = entry
                            If acBlockRef.EffectiveName = acBlockName Then  'есть reference
                                If referencedBlock = 2 Then
                                    DeleteBlock = -2   ' блок удалять нельзя
                                    Exit Function
                                End If
                                ub = ub + 1
                                ReDim Preserve iBlocksToDeleteArray(1 To ub)
                                iBlocksToDeleteArray(ub) = j
                                acBlockRef.Delete
                            End If
                        End If
                    Next
                End If
            Next
            If referencedBlock = 1 Then
                DeleteBlock = -1   ' из ссылающихся блоков удалены ссылки на удаляемый блок
                Exit Function
            End If
        Next
        i1 = i1 + 1
        If i1 > ub Then Exit Do
        DeleteBlock "!", referencedBlock
    Loop
    DeleteBlock = -10
End Function

Re: Как удалить блок из VBA

> rust2000
Большое спасибо. Функция отлично отработала.
Немного прояснилось по ссылкам. Я понимал, что дело в ссылках, но не мог в них разобраться.
Не подскажите, где можно более подробно данную тему изучить? Я использовал для изучения английскую книгу и help, но пробелы остались.

Re: Как удалить блок из VBA

Прошу прощения, что поднимаю старую тему, но непонятки остаются. Приведенная выше функция прекрасно работает, если объект, содержащий ссылку на блок находится на чертеже. Если же его стереть(erase), то приведенная выше функция ссылки не находит, но и блок удалить не может, ошибка та же самая - "имеется ссылка на блок". Если возможность удалить ссылки, которые находятся в стертых объектах? Либо как вообще в данной ситуации удалить блок?
Заранее спасибо.