Тема: «Потерянные блоки»

Здравствуйте уважаемые Знатоки. Имеется огромный чертеж который загружается и редактируется, крайне медленно. Я решил посмотреть его структуру.  Выделил блок, зашел в его свойства:  тип = Block Reference; Name = *U4. Понятно, что это вхождение блока, но имя начинается с *.  Отредактировать этот блок невозможно, так как не известно его имя. Чертеж чертил не я, поэтому процесс его создания мне не известен. Я предполагаю, что подобные блоки образовались в результате некорректного преобразования из другой программы.
В списке блоков чертежа, подобные блоки не отражаются вообще. Решил понять «природу» этого блока. Записал этот блок в отдельный файл , покопаться в VB,  стал просматривать объекты ThisDrawing.Blocks,  в свойствах Name блока вообще ничего не отражается, но объект присутствует.
Понимаю как очистить чертеж от описания блока когда отсутствуют его вхождения, но в данном случае наоборот вхождения блока есть, а связать их с блоком не могу. Вариант взорвать вхождения блока и создать новый блок не подходит, так как их очень много, а я один.
Очень жду ваших советов.

Re: «Потерянные блоки»

"Вариант взорвать вхождения блока и создать новый блок не подходит, так как их очень много"
Эта фраза звучит наивно если представить что все блоки можно обрабатывать в цикле.

Re: «Потерянные блоки»

[rus] Bloki nachinajushiesja na '*'- ehto t.n. anonimnye bloki. Obrazujutsja v rezul'tate razlichnyh dejstvij v AKADe. V dannom sluchae skoree vsego ehto dinamicheskie bloki s razlichnymi parametrami. Esli rabotaesh v 2006 AKADe mozhesh poluchit' dostup k istinnomu bloku cherez:
[/rus]

BlockRef.GetDynamicBlockProperties

В любом случае взрывать или ешхе чего делать с анонимными блоками(кроме конечно PURGE)[rus] net nikakogo rezona.
[/rus]

Re: «Потерянные блоки»

> Миша
Зря
Думаю другого пути у тебя нет, чем же цикл
насолил:
для каждого анонимного в рисунке
- вычилить точку вставки
- взорвать
- все объекты в массив
- создать блок с именем (хотя бы используя при
этом системную переменную "CDATE", типа:
"Temp_" & CStr(Thisdrawing.getvariable ("CDATE"))
- методом CopyObjects добавить массив объектов
во вновь созданный блок
- удалить родителей
- Regen
Это самый быстрый вариант без сравнения на
одинаковость,
минус только в том что будет куча клонов,
если не использовать фильтр для набора
А кто мешает применить?
Сугубо частное, IMHO
~'J'~

Re: «Потерянные блоки»

Совет несколько косвенный, но все же... может стоит просмотреть структуру чертежа через просмотровщик базы данных - dbview?
Глядишь, что нибудь и выяснится по поводу природы рассматриваемого феномена.

Re: «Потерянные блоки»

> Миша
Есть еще команда
BLOCKREPLACE
из пакета
Express Tools
но нет возможности проверить
Попробуй такой вариант с единичным блоком, можно
переделать под все анонимные, только есть вероятность
что некоторые могут являться составной частью
динамических блоков и не забудь,
что неименованные блоки которые начинаются
на "*Dnnn" или "*Xnnn" имеют хозяев в виде
измерений или штриховок
Код ужасный конечно, все на скорую руку...

Option Explicit
Sub RenameGhosts()
     Dim oEnt As AcadEntity, objCopy() As Object, _
         oBlock As AcadBlock, oblkRef As AcadBlockReference, _
         varPt, bName As String, oldName As String, _
         insPt As Variant, oItem As Object, _
         iCnt As Integer, jCnt As Integer
     On Error GoTo Err_Control
     ThisDrawing.Utility.GetEntity oEnt, varPt, vbCrLf & "Select unnamed (anonymous) block "
     If oEnt Is Nothing Then Exit Sub
     If TypeOf oEnt Is AcadBlockReference Then
          Set oblkRef = oEnt
          MsgBox oblkRef.Name
     End If
     oldName = oblkRef.Name
     If Left$(oldName, 2) <> "*U" Then Exit Sub
     iCnt = 0
     Set oBlock = ThisDrawing.Blocks.Item(oldName)
     insPt = oBlock.Origin
     jCnt = oBlock.Count - 1
     ReDim objCopy(jCnt) As Object
     For Each oItem In oBlock
          Set objCopy(iCnt) = oItem
          iCnt = iCnt + 1
     Next oItem
     bName = InputBox("Enter new name for unnamed block: ", "BLOCK NAME")
     Set oBlock = ThisDrawing.Blocks.Add(insPt, bName)
     ThisDrawing.CopyObjects objCopy, oBlock
     Dim oSset As AcadSelectionSet, _
         fcode(0) As Integer, _
         fData(0) As Variant, _
         dxfcode, dxfdata, _
         setName As String
     fcode(0) = 0
     fData(0) = "INSERT"
     dxfcode = fcode
     dxfdata = fData
     setName = "$Anonym$"
     For iCnt = 0 To ThisDrawing.SelectionSets.Count - 1
          If ThisDrawing.SelectionSets.Item(iCnt).Name = setName Then
               ThisDrawing.SelectionSets.Item(iCnt).Delete
               Exit For
          End If
     Next iCnt
     ZoomExtents
     Set oSset = ThisDrawing.SelectionSets.Add(setName)
     oSset.Select acSelectionSetAll, , , dxfcode, dxfdata
     If oSset.Count = 0 Then
          MsgBox "Empty set"
          Exit Sub
     End If
     Dim dblXscl As Double, dblYscl As Double, _
         dblZscl As Double, dblRot As Double, _
         layName As String
     iCnt = 0
     For Each oEnt In oSset
          Set oblkRef = oEnt
          If oblkRef.Name = oldName Then
               insPt = oblkRef.InsertionPoint
               dblXscl = oblkRef.XScaleFactor
               dblYscl = oblkRef.YScaleFactor
               dblZscl = oblkRef.ZScaleFactor
               dblRot = oblkRef.Rotation
               layName = oblkRef.Layer
               oblkRef.Delete
               Set oblkRef = _
               ThisDrawing.ActiveLayout.Block.InsertBlock(insPt, bName, dblXscl, dblYscl, dblZscl, dblRot)
               oblkRef.Layer = layName
               oblkRef.Update
               iCnt = iCnt + 1
          End If
     Next
     MsgBox "There are renamed " & iCnt & " blocks " & Chr(34) & oldName & Chr(34)
     ThisDrawing.Regen acAllViewports
     Exit Sub
Err_Control:
     If Err Then MsgBox Err.Description
End Sub

~'J'~

Re: «Потерянные блоки»

Большое Вам всем спасибо!
Вариант с взрывом вхождений блоков я думаю не подойдет, по тому что вхождений блока в чертеже очень многочисленны, а это приведет к появлению большого числа блоков одинаковых по структуре, но разных по имени. Написать программу, которая анализировала и сравнивала содержимое блоков, пока мне не по зубам.
Наиболее реальный вариант это переопределить анонимный блок в обычный.
Спасибо за код, постараюсь разобраться, вроде бы все понятно. Вечером буду разбираться.
Еще раз большое Вам спасибо за помощь.

Re: «Потерянные блоки»

Уважаемые знатоки, я испробовал предложенный код. При помощи его удается выделенное вхождение анонимного блока переделать в вхождение блока с новым именем. Но все остальные вхождения анонимного блока остаются без изменения, как переопределить всех их к новому блоку?

Re: «Потерянные блоки»

> Андрей
Не знаю, у меня перевставляются все блоки с одинаковым
именем, например в моем чертеже 138 блоков "*U3"
и все переименовываются на указанное и перевставляются
Указываешь ты конечно один, а изменяются все
с этим именем...
Создай набор и пройдись циклом без всякого отдельного выбора
~'J'~

Re: «Потерянные блоки»

Подскажите пожалуйста, а как вы циклом находите скрытые одинаковые блоки. Ведь название одинаковое у всех вхождений скрытых блоков.

Re: «Потерянные блоки»

Если блок уже есть в чертеже, добавляй к имени блока единицу, если и такой блок есть то ещё добавь и так до тех пор пока не найдёш имя блока которого нет в чертеже

Re: «Потерянные блоки»

Подскажите пожалуйста, как можно программно организовать цикл всех вхождений блоков на чертеже.

Re: «Потерянные блоки»

> Андрей
Не нашел подходящего примера у себя
Попробуй такой вариант
Создай форму с одним лист боксом ListBox1
и кнопокой CommandButton1
Вставь в форму следующий код:
(не забудь изменить имя файла - отмечено в коде)

Option Explicit
Private Sub CommandButton1_Click()
Unload Me
End Sub
Private Sub UserForm_Initialize()
Call QTYBlocks
End Sub
  Private Sub QTYBlocks()
  Dim objAcad As AcadApplication
  Dim objDoc As AcadDocument
  Dim fName As String
  Dim oBlocks As AcadBlocks
  Dim oBlock As AcadBlock
  Dim oBlkRef As AcadBlockReference
  Dim oEnt As AcadEntity
  Dim fType(1) As Integer, fData(1)
  Dim oSset As AcadSelectionSet
  Dim blkName As String
  Dim iCount As Integer
  Dim dxfCode, dxfData
  Dim tmp(1)
  Dim blkColl As New Collection
  fType(0) = 0: fData(0) = "INSERT"
  fType(1) = 2
  fName = "D:\#BLOCKS\CHECKS.DWG" ' ' =>*** измени имя файла
On Error GoTo Err_Trapp
Set objAcad = CreateObject("AutoCAD.Application")
Set objDoc = objAcad.Documents.Open(fName, True)
For Each oSset In objDoc.SelectionSets
If oSset.Name = "$BlkInstances$" Then
Exit For
End If
Next oSset
Set oSset = objDoc.SelectionSets.Add("$BlkInstances$")
oSset.Clear
Set oBlocks = objDoc.Blocks
  For Each oBlock In oBlocks
  If oBlock.IsLayout = False And oBlock.IsXRef = False Then
  blkName = oBlock.Name
  fData(1) = blkName
  dxfCode = fType
  dxfData = fData
  oSset.Select acSelectionSetAll, , , dxfCode, dxfData
  iCount = 0
  For Each oBlkRef In oSset
  iCount = iCount + 1
    Next oBlkRef
    tmp(0) = blkName: tmp(1) = iCount
    blkColl.Add tmp
    Erase tmp
    DoEvents
    oSset.Clear
    End If
  Next oBlock
  oSset.Delete
  Set oSset = Nothing
  objDoc.Close
  objAcad.Quit
  Set objDoc = Nothing
  Set objAcad = Nothing
  Dim i As Long, j As Long
  ReDim blkvar(blkColl.Count - 1, 1) As String
  For i = 1 To blkColl.Count
  blkvar(i - 1, 0) = blkColl.Item(i)(0)
  blkvar(i - 1, 1) = blkColl.Item(i)(1)
  Next
  ListBox1.ColumnWidths = "5cm;0.5cm"
  ListBox1.list() = blkvar
Err_Trapp:
If Err Then
 MsgBox "Error! " & vbNewLine & Err.Description
 End If
End Sub

Создай модуль и вставь туда следующий код

Option Explicit
Sub RunMe()
UserForm1.Show
End Sub

Не забудь, что проект не должен запускаться из файла
который ты будешь тестировать, а если нужно
все-таки работать в этом же файле, тогда измени документ на
ThisDrawing и удали из кода все лишнее
Надеюсь методика будет понятна
~'J'~

Re: «Потерянные блоки»

Большое спасибо за подсказку! Вы мне очень помогли!

Re: «Потерянные блоки»

> Андрей
А вот как переименовать скрытый блок (или вложенный)
так и не получается, проблема в трансформации координат вставки,
так что поробуй сам, может у тебя будет идея получше
Успехов
~'J'~