Тема: Как программно скопировать все объекты в другой чертеж?

неподскажете, как можно программно скопировать все объекты чертежа и вставить в другой чертеж?
или же только можно брать координаты каждого объекта и строить его заново другом чертеже?

Re: Как программно скопировать все объекты в другой чертеж?

Для этого есть метод AcadDocument.CopyObjects

Re: Как программно скопировать все объекты в другой чертеж?

спасибо!
только что- то я не очень разобрался.
почему- то у меня не работает.

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

Re: Как программно скопировать все объекты в другой чертеж?

В хелпе, конечно, всё это есть:

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.

Т.е. нужно не набор объектов передавать в качестве параметра, а массив.

Re: Как программно скопировать все объекты в другой чертеж?

всё равно не работает...

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

Re: Как программно скопировать все объекты в другой чертеж?

Тоже мучался в свое время ... Заработало, когда стал копировать не просто в документ, а в пространство модели (doc.ModelSpace). Попробуйте разделить пространства модели и бумаги (если второе вообще вам интересно).

Re: Как программно скопировать все объекты в другой чертеж?

Вот "выжимка" кода (копируется, правда, только один блок)
   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)

Re: Как программно скопировать все объекты в другой чертеж?

Пока я мучился отлаживал эту штуку, 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 - переменная - параметр, а с большой буковки - глобальная переменная. Это облегчает отладку и читаемость кода.

Re: Как программно скопировать все объекты в другой чертеж?

работает!
спасибо!

Re: Как программно скопировать все объекты в другой чертеж?

но когда я после этого в тот же самый чертеж (куда был скопирован первый) пытаюсь скопировать другой чертеж, то он не копируется.

Re: Как программно скопировать все объекты в другой чертеж?

Можно поподробнее задачу описать? Или фрагмент проблемного кода. Те два нюанса о которых я говорил, как они?

Re: Как программно скопировать все объекты в другой чертеж?

нужно сначала один чертеж скопировать в новый, а потом туда же- ещё один
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

Re: Как программно скопировать все объекты в другой чертеж?

В вопросе звучит - "... скопировать в один чертёж", а в коде

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 

Может это выход из положения??? Почему такая дурь творится я не знаю.
Процедурка ?аа? поочерёдно копирует все открытые файлы в последний.

Re: Как программно скопировать все объекты в другой чертеж?

у меня они копируются, но не в отдельный чертеж, а во второй. и притом неоднократно.
я пытаюсь вместо

Set pACD = Documents.Item(Documents.Count - 1)

написать

Set pACD = New AcadDocument

но это ничего не меняет.....
а как можно сделать, чтоб открывалось новое окно автокада, там уже создавался новый документ и копировалось все туда?

Re: Как программно скопировать все объекты в другой чертеж?

У меня практически нет опыта работы с многими документами одновременно. Я обхожусь импортом, экспортом, вставкой блоков, вставкой файлов ...
Из того опыта, что у меня есть:
1)Если режим работы однодокументный, то команда Set pACD = New AcadDocument автоматом запускает новый экземпляр Автокада и в нём новый документ.
2)Режим многодокументный - эта же строчка создаёт новый документ в ряду уже имеющихся, открытых в данном сеансе работы.
Когда я тестировал пример  JS (2005-10-05 19:30:31), то сначала пооткрывал несколько штук файлов, потом создал новый - пустой, он, естественно, в списке оказался с номером Documents.Count - 1, а затем запускал пример. Точно в таком же режиме копировать все объекты сразу, не по одному, не получалось. Работало так: первый файл копирует, второй и дальше - "инвалид оунер...", а если в списке документов были вновь созданные, а не старые, то из них тоже нормально копировал как из первого. Я так и не смог понять, что за проблемы. Но при копировании по одному - JS (2005-10-05 19:30:31), всё копировалось изо всех чертежей в один - последний нормально. Обращаться к документам в коллекции документов, наверное можно и по имени. Я сам не пробовал, т.к. не работаю в многодокументном режиме. Таким образом, если последний в коллекции документ не то, что надо, то надо брать то что надо. Вроде это не должно сильно затруднять.
Может быть стоит принципиально изменить подход. Создать новый документ, и загрузить вставкой всё, что требуется, из разных файлов?

Re: Как программно скопировать все объекты в другой чертеж?

нет, изменить подход не получится.
нужно, чтобы автокад запускался повторно уже после запуска программы. так как мне необходимо, чтобы работала программа и одновременно можно было работать в автокаде.
кстати. строчка
Set pACD = New AcadDocument
у меня создает новый документ в том же автокаде, а не в новом.
но для начала меня бы устроило копирование в новый чертеж в том же автокаде,
но, если я заменяю
Set pACD = Documents.Item(Documents.Count - 1)
на
Set pACD = New AcadDocument ,
копирования вообще не происходит.

Re: Как программно скопировать все объекты в другой чертеж?

Ещё раз внимательно почитай то, что я написал JS (2005-10-10 16:18:25). Потом, если не решишь проблему, то подробно напиши, что конкретно нужно сделать. Может я пойму что надо и тогда смогу помочь.

Re: Как программно скопировать все объекты в другой чертеж?

нет, в новый документ у меня никак не копируется, как я ни пробовал.

Re: Как программно скопировать все объекты в другой чертеж?

Ну прям не знаю, что и сказать. Еще раз попробовал по другому:

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
Всё скопировалось! Не знаю что и сказать теперь!!!

Re: Как программно скопировать все объекты в другой чертеж?

заработало!!!!
спасибо, JS!
только непонятно, почему все объекты во вновь созданном чертеже оказываются влепленными в один угол чертежа.
еще бы хотелось, чтобы копировалось в чертеж, созданный в новом окне автокада.

Re: Как программно скопировать все объекты в другой чертеж?

Dim pACA As AcadApplication
    Set pACA = CreateObject("AutoCAD.Application")
    pACA.Visible = True

Re: Как программно скопировать все объекты в другой чертеж?

Новый вопрос -- новая тема: Почему иногда при копировании резко возрастает количество объектов?.
/Администратор./

Re: Как программно скопировать все объекты в другой чертеж?

еще такой вопрос.
если я хочу копировать все объекты открытых чертежей в чертеж в новом автокаде, я пишу так

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

но почему- то копирования в таком случае не происходит

Re: Как программно скопировать все объекты в другой чертеж?

Да, несмотря на то, что я нашёл и исправил некоторые глупости в тех программульках, что здесь писал, и те, что у тебя есть - результат печальный - "QueryInterface IID_IAcadBaseObject fails"
Видимо чего-то мы тут сильно не понимаем. Но мне, всё таки, кажется странным такой вариант создания нового чертежа. Зачем в многодокументном режиме открывать новый сеанс Автокада?

Re: Как программно скопировать все объекты в другой чертеж?

потому что старый заблокирован выводимой формой.
нужно, чтобы и форма была активна, и к чертежам был доступ.