Тема: Как программно сделать импорт блока из другого файла?
Здраствуйте!
Имеется файл 1.dwg (не открыт) в кот находиться блок под именем "А". Как программно вставить указанный блок в любой активный чертеж, не открывая файла.
Информационный портал для профессионалов в области САПР
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Форумы CADUser → Программирование → VBA → Как программно сделать импорт блока из другого файла?
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Здраствуйте!
Имеется файл 1.dwg (не открыт) в кот находиться блок под именем "А". Как программно вставить указанный блок в любой активный чертеж, не открывая файла.
> Илья
Если непременно надо, чтобы чертёж с блоком "А" НЕ открывался в Акаде, тогда путь один - писать приложение, непосредственно читающее с диска dwg-чертёж. В этом поможет http://www.opendwg.org, раздел download, там есть бесплатные спецификации вплоть до 2000 версии включительно. Но если вы в здравом рассудке:), то лучше ОТКРОЙТЕ файл, содержащий блок "А", а дальше вам поможет https://www.caduser.ru/forum/topic14682.html, там, правда, на Visual Lispe, но я думаю, вы этот язык уже знаете:).
...Visual Lispe, но я думаю, вы этот язык уже знаете
Интересно из чего это следует?
Я программирую на VB6. Так уж сложилось, что я ег оизучаю со школьной скамьи.
Когда-то видел такую запись InsertBlock.Databases...
Но в синтаксисе не могу разобраться.
В принципе должна реализовываться такая ситуация.
Если в активный чертеж вставить другой чертеж (в кот имеет блоки), а затем его удалить, то в список имеющихся блоков будут занесены все блоки из вставленного (а затем удаленного) чертежа.
Можно конечно реализовать ситуацию с загрузкой нужного чертежа (но без его отображения) и работать через команды Select и Paste, но это будет загружать буфер обмена.
Хотя подойде и этот вариант.
Если в активный чертеж вставить другой чертеж (в кот имеет блоки), а затем его удалить, то в список имеющихся блоков будут занесены все блоки из вставленного (а затем удаленного) чертежа.
Это очень грязный приём. Лично я предлагаю через команду _WBLOCK (в той ветке https://www.caduser.ru/forum/topic14682.html всё подробно описано). Извините, что не могу дать рекомендацию по VB, сейчас нет времени.
Это очень грязный приём.
Вот уж не думал, что в программировании есть такое понятие.
> Илья
Сейчас нашёл свободное время, вот наваял:)
Инструкции:
1.открыть новый чертёж, alt-F11 (надеюсь, знаешь:))
2.создать в проекте новый модуль (не класс!), оставить название по умолчанию и вклеить туда этот код:
Attribute VB_Name = "Module1" Option Explicit Const lib_name = "library.dwg" 'название файла-библиотеки Const temp_file_path = "c:\" 'полный путь до временного файла Public blk_name As String 'имя выбранного юзером блока Sub head() Dim lib As AcadDocument Dim i As Integer Dim error_msg As String Set lib = Nothing error_msg = "Библиотечный файл " & lib_name & " не открыт" For i = 0 To AcadApplication.Documents.Count - 1 If AcadApplication.Documents.Item(i).Name = lib_name Then Set lib = AcadApplication.Documents.Item(i) End If Next i If ActiveDocument.Name = lib_name Then error_msg = "Библиотечный файл " & lib_name & " не должен быть активным документом" Set lib = Nothing End If If lib Is Nothing Then MsgBox error_msg Else insert_block_from_library lib End If End Sub Private Sub insert_block_from_library(lib As AcadDocument) Dim blk As AcadBlock Dim i As Integer Dim already_present As Boolean Dim user_doc As AcadDocument Dim old_filedia As Integer UserForm1.ListBox1.Clear For Each blk In lib.Blocks If Not (Left(blk.Name, 1) = "*") Then UserForm1.ListBox1.AddItem blk.Name Next blk blk_name = "" UserForm1.show If blk_name = "" Then MsgBox "Не был выбран блок" Else For i = 0 To ActiveDocument.Blocks.Count - 1 If ActiveDocument.Blocks.Item(i).Name = blk_name Then ActiveDocument.SendCommand "_.-insert" & vbCr & blk_name & vbCr already_present = True End If Next i If Not already_present Then Set user_doc = ActiveDocument old_filedia = lib.GetVariable("FILEDIA") lib.SetVariable "FILEDIA", 0 lib.SendCommand "_.-wblock" & vbCr & temp_file_path & blk_name & ".dwg" & vbCr & blk_name & vbCr lib.SetVariable "FILEDIA", old_filedia user_doc.SendCommand "_.-insert" & vbCr & temp_file_path & blk_name & ".dwg" & vbCr End If End If End Sub
3. создать в проекте форму, оставить имя по умолчанию, создать на ней листбокс (НЕ комбобокс!), оставить ему имя по умолчанию, щёлкнуть по нему мышой и добавить следующий код:
Option Explicit Private Sub ListBox1_Change() If Me.ListBox1.ListCount > 0 Then Module1.blk_name = Me.ListBox1.Value Me.Hide End Sub
На этом всё. Можно создать в меню на тулбаре графическую кнопку с макрокодом:
^C^C_.-vbarun;head;
Теперь "руководство пользователя".
1. должен быть открыт чертёж с именем library.dwg (храниться он может в любом месте, хоть на сервере), в котором в пространстве модели определены несколько блоков. При вызове макроса этот чертёж не должен быть активен!
2. юзер должен работать с любыми другими чертежами, и, когда ему захочется, вызывать макрос "head" (можно через графическую кнопку меню на тулбаре). Можно также редактировать как угодно чертёж-библиотеку library.dwg, но работая в ней, повторяю, вызывать макрос нельзя (хотя эта ситуация нормально обрабатывается в макросе и не приводит к краху системы:))
3. важное замечание: при вставке блока в юзерский чертёж макрос сначала ищет такой блок в этом же файле, и только если не находит, вставляет из файла-библиотеки. Это значит, что если в библиотеке более свежие блоки, то юзеру надо удалить все вхождения этих блоков в своём чертеже и сделать команду PURGE, чтобы избавиться от старых определений блоков. После этого при первой же вставке блока через макрос, блок будет не найден в текущем чертеже и взят уже из библиотеки, более свежий. В принципе, это тоже несложно автоматизировать:).
Ой, строка Attribute VB_Name = "Module1" в самом начале кода не нужна, она попала случайно!!! Первой строкой должна быть Option Explicit
Добрый день. Если можно, то поясните:
1) Как при вставки блока исключить появления запроса об масштабе и угле вставки блока;
2) Как удалить временный файл с изображением блока.
Пожалуйста, ответьте мне на мой вопрос.
1) Как при вставки блока исключить появления запроса об масштабе и угле вставки блока;
2) Как удалить временный файл с изображением блока.
> Андрей
Мне так кажется нужно просто в коде указать, чему равен масштаб, и угол вставки, и тогда запрос не будет появляться
Подскажите пожалуйста, как в коде это указать. С учетом, что координату вставляемого блока, я хочу выбирать при помощи мыши.
Я работаю таким образом:
Загрузка блока из другого файла
Sub loadBlock4(fileName$, blockName$) 'Цель: Загрузка блока в активный файл из другого файла 'Дано: 'fileName$ - имя файла, содержащего требуемый блок 'blockName$ - имя требуемого блока 'Результат: Требуемый блок загружен в активный файл 'чтение содержимого текущего файла. Нижеследующую конструкцию сделал, т.к. 'при каких-то изменениях в меню Window, теряется свойство Active у видимого файла Dim targetDoc As AcadDocument 'имя файла, в который надо загрузить блок Dim i%, n%: n = Documents.Count 'общее количество файлов в приложении For i = 0 To n - 1 If Documents(i).Active Then Set targetDoc = Documents.Item(i) 'комплект-набор текущего файла Next i 'работа с файлом-донором 'открытие файла On Error GoTo myExit1 'если нет файла в данном компьютере ThisDrawing.Application.Documents.Open (fileName) myExit1: If Err <> 0 Then Err.Clear Dim Res1: Res1 = "В этом компьютере нет файла " & fileName & "." Res1 = MsgBox(Res1, vbOKOnly, "MyLibrary4, modACAD, Sub loadBlock") End End If 'чтение содержимого файла Dim sourceDoc As AcadDocument n = Documents.Count For i = 0 To n - 1 If Documents(i).FullName = fileName Then Set sourceDoc = Documents.Item(i) Next i 'проверка наличия требуемого блока Dim oBlocks As AcadBlocks: Set oBlocks = ThisDrawing.Blocks 'коллекция блоков n = ThisDrawing.Blocks.Count 'общее количество блоков в файле Dim isBlock As Boolean: isBlock = False Set oBlocks = sourceDoc.Blocks 'коллекция блоков в файле-доноре Dim oBlock As AcadBlock: Set oBlock = oBlocks.Item(blockName) 'искомый блок For i = 0 To n - 1 If oBlocks(i).Name = blockName$ Then isBlock = True Next i If Not isBlock Then Res1 = "В файле " & fileName & Chr(10) Res1 = Res1 & "нет блока " & blockName Res1 = MsgBox(Res1, vbOKOnly, "MyLibrary4, modACAD, Sub loadBlock") End End If 'загрузка блока в текущий файл Dim objCopy(0) As AcadObject: Set objCopy(0) = oBlock 'копия блока Dim RetVal 'Variant (array of objects). Массив вновь созданных дубликатов объектов. 'Only primary objects are returned in this array Dim IDPairs 'Variant (array of IDPair objects); input-output; optional 'Information on what happened during the copy and translation process. 'Input: an empty variant. 'Output: an array of IDPair objects RetVal = sourceDoc.CopyObjects(objCopy, targetDoc.Blocks, IDPairs) 'заключительные работы sourceDoc.Close False: Set sourceDoc = Nothing 'закрытие файла-донора End Sub
Вставка блока программно
Function InsertBlock3(blName$, pBase() As Double, _ Optional Sc# = 1, Optional xs# = 1, Optional ys# = 1, Optional zs# = 1, _ Optional Layer$ = "активный", Optional blExplode As Boolean = False) 'Цель: Вставка блока 'Дано: 'blName - имя вставляемого блока 'pBase() - координаты вставки и угол поворота блока в радианах или формулой: градусы / 180 * Pi. 'Если угол > 0, блок поворачивается против часовой стрелки 'Sc# = 1 - масштаб для координат точки вставки блока 'xs# = 1 - масштаб блока по оси X. При xs < 0 блок отображается зеркально относитель-но оси X 'ys# = 1 - масштаб блока по оси Y. При ys < 0 блок отображается зеркально относитель-но оси Y 'zs# = 1 - масштаб блока по оси Z. При zs < 0 блок отображается зеркально относительно оси Z 'Layer$ = "активный". AcadBlockReference вставляется в текущий слой 'blEx - признак необходимости разрушить блок 'установка слоя текущим If Layer$ <> "активный" Then Call ChangeLayerCur3(Layer$) 'определение координат точки вставки с учетом масштаба Dim BlockRotation#, insertionPnt(0 To 2) As Double insertionPnt(0) = pBase(0) * Sc: insertionPnt(1) = pBase(1) * Sc: insertionPnt(2) = pBase(2) * Sc 'чтение угла поворота блока BlockRotation = pBase(3) 'вставка блока Dim CurBlockRefObj As AcadBlockReference Set CurBlockRefObj = ThisDrawing.ModelSpace.InsertBlock(insertionPnt, blName, xs, ys, zs, BlockRotation) 'разрушение блока If blExplode Then CurBlockRefObj.Explode End Function
Все хорошо. Но оператор
"Set oBlock = oBlocks.Item(blockName) 'искомый блок
Обращается за блоком раньше чем происходит проверка на его наличие, что приводит к ошибке, которая перехватывается как отсутствие файла ...
если его поставить пониже, то ОК.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Форумы CADUser → Программирование → VBA → Как программно сделать импорт блока из другого файла?
Форум работает на PunBB, при поддержке Informer Technologies, Inc