Тема: Как программно скопировать все объекты в другой чертеж?
неподскажете, как можно программно скопировать все объекты чертежа и вставить в другой чертеж?
или же только можно брать координаты каждого объекта и строить его заново другом чертеже?
Информационный портал для профессионалов в области САПР
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Форумы CADUser → Программирование → VBA → Как программно скопировать все объекты в другой чертеж?
Чтобы отправить ответ, вы должны войти или зарегистрироваться
неподскажете, как можно программно скопировать все объекты чертежа и вставить в другой чертеж?
или же только можно брать координаты каждого объекта и строить его заново другом чертеже?
Для этого есть метод AcadDocument.CopyObjects
спасибо!
только что- то я не очень разобрался.
почему- то у меня не работает.
Private Sub myCopy_Click(doc1 As acadDocument) Dim objSelCol As AcadSelectionSets Set objSelCol = ThisDrawing.SelectionSets Dim doc2 As AcadDocument Set doc2 = New AcadDocument Call doc1.CopyObjects(objSelCol, doc2) doc2.Activate End Sub
В хелпе, конечно, всё это есть:
RetVal = object.CopyObjects(Objects[, Owner][, IDPairs])
Object
Database, Document
The object or objects this method applies to.
Objects
Variant (array of objects); input-only
The array of primary objects to be copied. All the objects must have the same owner, and the owner must belong to the database or document that is calling this method.
Owner
Variant (a single object); input-only; optional
The new owner for the copied objects. If no owner is specified, the objects will be created with the same owner as the objects in the Objects array.
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
Variant (array of objects)
An array of newly created duplicate objects. Only primary objects are returned in this array. For more information on what occured during the CopyObjects operation, or a list of objects owned by primary objects that were also copied, consult the IDPairs array.
Т.е. нужно не набор объектов передавать в качестве параметра, а массив.
всё равно не работает...
Private sub my_copy(doc1 as AcadDocument) Dim objSelSet As AcadSelectionSet Dim objEnt As AcadEntity Dim doc2 As AcadDocument Dim allObj() As Variant Dim i As Long Set doc2 = New AcadDocument doc1.Activate Set objSelSet = vbdPowerSet("processall") objSelSet.Select acSelectionSetAll i = 0 For Each objEnt In objSelSet ReDim Preserve allObj(i + 1) As Variant Set allObj(i) = objEnt i = i + 1 Next Call doc1.CopyObjects(allObj, doc2) doc2.Activate end sub Private Function vbdPowerSet(strName As String) As AcadSelectionSet Dim objSelSet As AcadSelectionSet Dim objSelCol As AcadSelectionSets Set objSelCol = ThisDrawing.SelectionSets For Each objSelSet In objSelCol If objSelSet.name = strName Then objSelSet.Delete Exit For End If Next Set objSelSet = ThisDrawing.SelectionSets.Add(strName) Set vbdPowerSet = objSelSet End Function
Тоже мучался в свое время ... Заработало, когда стал копировать не просто в документ, а в пространство модели (doc.ModelSpace). Попробуйте разделить пространства модели и бумаги (если второе вообще вам интересно).
Вот "выжимка" кода (копируется, правда, только один блок)
Dim objCollection(0 To 0) As Object
Dim retObj As Variant
Set src = Application.ActiveDocument
Set objCollection(0) = src.Blocks.Item ( "Имя_блока")
Set dst = Application.Documents.Add
retObj = src.CopyObjects(objCollection, dst.ModelSpace)
Пока я мучился отлаживал эту штуку, Sigma дал толковый совет. Правда, мне оказалось недостаточно этого. Кроме того, что надо подставлять в параметры именно блок, а не документ, ещё не срабатывал вызов метода от ссылки на вновь созданный документ. Да и переменная исходного документа тоже оказывалась ссылающейся на вновь созданный документ. Наверное прочитать, то что написал тяжело, а разобраться что и как и того хуже.
Итак вот код который у меня заработал:
Private Sub my_copy(ByVal vACD As AcadDocument) Dim pSS As AcadSelectionSet Dim pE As AcadEntity Dim pACD As AcadDocument Dim pArrE() As AcadEntity Dim i As Long, n As Long Dim pRet, pIdP Dim ErrResult As String On Error Resume Next PrepareSelSet vACD, "ss", pSS pSS.Select acSelectionSetAll n = pSS.Count If n > 0 Then ReDim pArrE(0 To n - 1) For i = 0 To n - 1 Set pArrE(i) = pSS.Item(i) Next i Set pACD = Documents.Add pArrE(0).Document.CopyObjects pArrE, pACD.ModelSpace '''pRet = pArrE(0).Document.CopyObjects(pArrE, pACD.ModelSpace, pIdP) pACD.Activate End If If Err Then Err.Clear End Sub Public Sub PrepareSelSet(vAcadDoc As AcadDocument, ss As String, SSet As AcadSelectionSet) On Error Resume Next Set SSet = vAcadDoc.SelectionSets.Item(ss) If Err Then Err.Clear Set SSet = vAcadDoc.SelectionSets.Add(ss) Else SSet.Clear End If End Sub
Кроме отмеченного Sigma момента ещё два нюанса.
1) vbdPowerSet - нехорошо в многодокументном режиме. ThisDrawing трудно отследить на кого ссылается. Я в своём коде использую более явную процедуру PrepareSelSet. Да и вообще я создание всех объектов (слой, стиль, блок ...) делаю такими процедурами, начинающимися с Prepare... Это очень удобно.
2)Вызов метода CopyObjects от непонятно как и когда нарушенной переменной не проходил. Спасло то, что вызвал так как приведено выше:pArrE(0).Document.CopyObjects , т.е. через ссылку на исходный документ в одном из копируемых объектов(в первом). Вот такой дурдом.
Темя апострофами отмечен альтернативный вызов (тоже работает), если нужен доступ к вновь созданным объектам.
И наконец прошу прощения за то, что переименовал все переменные. Я в какой то книжечке подглядел, что если именовать переменные с буковки m, то это переменные уровня модуля, если с буковки p, то уровня процедуры, v - переменная - параметр, а с большой буковки - глобальная переменная. Это облегчает отладку и читаемость кода.
работает!
спасибо!
но когда я после этого в тот же самый чертеж (куда был скопирован первый) пытаюсь скопировать другой чертеж, то он не копируется.
Можно поподробнее задачу описать? Или фрагмент проблемного кода. Те два нюанса о которых я говорил, как они?
нужно сначала один чертеж скопировать в новый, а потом туда же- ещё один
gthdsq- то у меня копируется нормально. а вот второй- нет....
Private Sub my_copy(ByVal vACD1 As AcadDocument, ByVal vACD2 as AcadDocument) Dim pSS As AcadSelectionSet Dim pE As AcadEntity Dim pACD As AcadDocument Dim pArrE() As AcadEntity Dim i As Long, n As Long Dim pRet, pIdP Dim ErrResult As String On Error Resume Next PrepareSelSet vACD1, "ss", pSS pSS.Select acSelectionSetAll n = pSS.Count If n > 0 Then ReDim pArrE(0 To n - 1) For i = 0 To n - 1 Set pArrE(i) = pSS.Item(i) Next i Set pACD = Documents.Add pArrE(0).Document.CopyObjects pArrE, pACD.ModelSpace ' pACD.Activate End If PrepareSelSet vACD2, "ss", pSS pSS.Select acSelectionSetAll n = pSS.Count If n > 0 Then ReDim pArrE(0 To n - 1) For i = 0 To n - 1 Set pArrE(i) = pSS.Item(i) Next i Set pACD = Documents.Add pArrE(0).Document.CopyObjects pArrE, pACD.ModelSpace pACD.Activate End If If Err Then Err.Clear End Sub Public Sub PrepareSelSet(vAcadDoc As AcadDocument, ss As String, SSet As AcadSelectionSet) On Error Resume Next Set SSet = vAcadDoc.SelectionSets.Item(ss) If Err Then Err.Clear Set SSet = vAcadDoc.SelectionSets.Add(ss) Else SSet.Clear End If End Sub
В вопросе звучит - "... скопировать в один чертёж", а в коде
Set pACD = Documents.Add
встречается дважды? То есть создаются два документа. Но это ничего не меняет. Я уже часа два пробую пробить эту штуку и всё равно ?Инвалид оунер??.
Потом я уже от отчаяния взял свою старенькую процедурку которая копирует по одному объекту? и о счастье! Стало получаться.
Sub aa() Dim pACD1 As AcadDocument, pACD2 As AcadDocument Dim pACD As AcadDocument Static pNDoc As Long Dim pE As AcadEntity On Error GoTo erhan If pNDoc = Documents.Count - 1 Then pNDoc = 0 Set pACD1 = Documents.Item(pNDoc) pNDoc = pNDoc + 1 If MsgBox("Вставляю файл " & pACD1.Name, vbOKCancel) = vbCancel Then Exit Sub Set pACD = Documents.Item(Documents.Count - 1) For Each pE In pACD1.ModelSpace CopyToBlock pE, pACD.ModelSpace Next pE pACD.Activate Update ZoomAll MsgBox "Вставлен файл " & pACD1.Name & vbCrLf & "Всё видно?" Exit Sub erhan: MsgBox Err.Description If Err Then Err.Clear End Sub Public Function CopyToBlock(Ent As AcadEntity, _ ToBlock As AcadBlock, Optional ByVal ErrResult As String, Optional NewBase = Null) As AcadEntity Dim t0(2) As Double, t1(2) As Double Dim pAO(0) As AcadEntity Dim pRet, pIdP Dim pACD As AcadDocument Set pACD = Ent.Document Set pAO(0) = Ent pRet = pACD.CopyObjects(pAO, ToBlock, pIdP) If Not IsNull(NewBase) Then On Error Resume Next t0(0) = NewBase(0) t0(1) = NewBase(1) t0(2) = NewBase(2) pRet(0).Move t0, t1 If Err Then Err.Clear End If Set CopyToBlock = pRet(0) End Function
Может это выход из положения??? Почему такая дурь творится я не знаю.
Процедурка ?аа? поочерёдно копирует все открытые файлы в последний.
у меня они копируются, но не в отдельный чертеж, а во второй. и притом неоднократно.
я пытаюсь вместо
Set pACD = Documents.Item(Documents.Count - 1)
написать
Set pACD = New AcadDocument
но это ничего не меняет.....
а как можно сделать, чтоб открывалось новое окно автокада, там уже создавался новый документ и копировалось все туда?
У меня практически нет опыта работы с многими документами одновременно. Я обхожусь импортом, экспортом, вставкой блоков, вставкой файлов ...
Из того опыта, что у меня есть:
1)Если режим работы однодокументный, то команда Set pACD = New AcadDocument автоматом запускает новый экземпляр Автокада и в нём новый документ.
2)Режим многодокументный - эта же строчка создаёт новый документ в ряду уже имеющихся, открытых в данном сеансе работы.
Когда я тестировал пример JS (2005-10-05 19:30:31), то сначала пооткрывал несколько штук файлов, потом создал новый - пустой, он, естественно, в списке оказался с номером Documents.Count - 1, а затем запускал пример. Точно в таком же режиме копировать все объекты сразу, не по одному, не получалось. Работало так: первый файл копирует, второй и дальше - "инвалид оунер...", а если в списке документов были вновь созданные, а не старые, то из них тоже нормально копировал как из первого. Я так и не смог понять, что за проблемы. Но при копировании по одному - JS (2005-10-05 19:30:31), всё копировалось изо всех чертежей в один - последний нормально. Обращаться к документам в коллекции документов, наверное можно и по имени. Я сам не пробовал, т.к. не работаю в многодокументном режиме. Таким образом, если последний в коллекции документ не то, что надо, то надо брать то что надо. Вроде это не должно сильно затруднять.
Может быть стоит принципиально изменить подход. Создать новый документ, и загрузить вставкой всё, что требуется, из разных файлов?
нет, изменить подход не получится.
нужно, чтобы автокад запускался повторно уже после запуска программы. так как мне необходимо, чтобы работала программа и одновременно можно было работать в автокаде.
кстати. строчка
Set pACD = New AcadDocument
у меня создает новый документ в том же автокаде, а не в новом.
но для начала меня бы устроило копирование в новый чертеж в том же автокаде,
но, если я заменяю
Set pACD = Documents.Item(Documents.Count - 1)
на
Set pACD = New AcadDocument ,
копирования вообще не происходит.
Ещё раз внимательно почитай то, что я написал JS (2005-10-10 16:18:25). Потом, если не решишь проблему, то подробно напиши, что конкретно нужно сделать. Может я пойму что надо и тогда смогу помочь.
нет, в новый документ у меня никак не копируется, как я ни пробовал.
Ну прям не знаю, что и сказать. Еще раз попробовал по другому:
Public Sub PrintMessage(MessageString As String) Dim pEchoVal As Integer pEchoVal = ThisDrawing.GetVariable("CMDECHO") ThisDrawing.SetVariable "CMDECHO", 1 ThisDrawing.Utility.Prompt MessageString ThisDrawing.SetVariable "CMDECHO", pEchoVal End Sub Public Function CopyToBlock(Ent As AcadEntity, _ ToBlock As AcadBlock, Optional ByVal ErrResult As String, Optional NewBase = Null) As AcadEntity Dim t0(2) As Double, t1(2) As Double Dim pAO(0) As AcadEntity Dim pRet, pIdP Dim pACD As AcadDocument On Error Resume Next Set pACD = Ent.Document Set pAO(0) = Ent pRet = pACD.CopyObjects(pAO, ToBlock, pIdP) If Not IsNull(NewBase) Then t0(0) = NewBase(0) t0(1) = NewBase(1) t0(2) = NewBase(2) pRet(0).Move t0, t1 End If If Err Then If Not IsMissing(ErrResult) Then ErrResult = Err.Description Else ErrResult = "" Err.Clear End If Set CopyToBlock = pRet(0) End Function Sub aa() Dim pACDDest As AcadDocument Dim pACD As AcadDocument Dim pErrRes As String Dim pNErr As Long Dim pE As AcadEntity PrintMessage vbCrLf & ">>>>>>>Начало работы AA" Set pACDDest = Documents.Add pACDDest.Activate PrintMessage vbCrLf & "Создали документ " & pACDDest.Name If Documents.Count = 1 Then Exit Sub For Each pACD In Documents If Not pACD Is pACDDest Then PrintMessage vbCrLf & "Копируем файл " & pACD.Name pNErr = 0 For Each pE In pACD.ModelSpace CopyToBlock pE, pACDDest.ModelSpace, pErrRes If pErrRes <> "" Then pNErr = pNErr + 1 Next pE If pNErr > 0 Then PrintMessage vbCrLf & "Ошибок при вставке файла " & pNErr Else PrintMessage " Успешно!" End If End If Next pACD pACDDest.Activate Update ZoomAll PrintMessage vbCrLf & "<<<<<<<Конец работы AA" End Sub
В результате после запуска AA создаётся новый документ и в него по очереди копируются все остальные. работает как часы. Вот что во вновь созданном документе отпечталось:
Создали документ Drawing7.dwg
Копируем файл Veryfi.dwg Успешно!
Копируем файл MSPDoc.dwg Успешно!
Копируем файл MegaFlex.dwg Успешно!
Копируем файл Свиньи.dwg Успешно!
Копируем файл Drawing1.dwg Успешно!
Копируем файл Drawing2.dwg Успешно!
Копируем файл Drawing3.dwg Успешно!
Копируем файл Drawing4.dwg Успешно!
Копируем файл Drawing5.dwg Успешно!
Копируем файл Drawing6.dwg Успешно!
Command:
Command:
<<<<<<<Конец работы AA
Строчка >>>>>>>Начало работы AA осталась в Drawing6.dwg
Всё скопировалось! Не знаю что и сказать теперь!!!
заработало!!!!
спасибо, JS!
только непонятно, почему все объекты во вновь созданном чертеже оказываются влепленными в один угол чертежа.
еще бы хотелось, чтобы копировалось в чертеж, созданный в новом окне автокада.
Dim pACA As AcadApplication Set pACA = CreateObject("AutoCAD.Application") pACA.Visible = True
Новый вопрос -- новая тема: Почему иногда при копировании резко возрастает количество объектов?.
/Администратор./
еще такой вопрос.
если я хочу копировать все объекты открытых чертежей в чертеж в новом автокаде, я пишу так
Dim pACA As AcadApplication Set pACA = CreateObject("AutoCAD.Application") pACA.Visible = True Set pACDDest = pACA.Documents.Add If Documents.Count = 1 Then Exit Sub For Each pACD In Documents If Not pACD Is pACDDest Then pNErr = 0 For Each pE In pACD.ModelSpace ... Next pACD next
но почему- то копирования в таком случае не происходит
Да, несмотря на то, что я нашёл и исправил некоторые глупости в тех программульках, что здесь писал, и те, что у тебя есть - результат печальный - "QueryInterface IID_IAcadBaseObject fails"
Видимо чего-то мы тут сильно не понимаем. Но мне, всё таки, кажется странным такой вариант создания нового чертежа. Зачем в многодокументном режиме открывать новый сеанс Автокада?
потому что старый заблокирован выводимой формой.
нужно, чтобы и форма была активна, и к чертежам был доступ.
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Форумы CADUser → Программирование → VBA → Как программно скопировать все объекты в другой чертеж?
Форум работает на PunBB, при поддержке Informer Technologies, Inc