Author Topic: Help with code to merge multiple Objects from 4 drawings into 1 new drawing  (Read 4054 times)

0 Members and 1 Guest are viewing this topic.

RMS

  • Guest
Hi Guys,

The code I am posting is from the AutoCad Developers site, I removed some comments to unclutter things a bit. In Part 1 the code copys a selected set of objects and this portion of code is good. But in Part 2 I need help;  I need to keep inserting a few selction sets from part 1 from 4 existing drawings into 1 drawing this one can be a template; But right now the code in part 2 just keeps opening a new template. If I can get an example of how to correct part 2 that would be great!

Code: [Select]
    <CommandMethod("pic")> _
    Public Sub SelectObjectsOnscreen()

        Dim acObjIdColl As ObjectIdCollection = New ObjectIdCollection()

        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        Dim acCurDb As Database = acDoc.Database

        Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

            Dim acSSPrompt As PromptSelectionResult = acDoc.Editor.GetSelection()

            If acSSPrompt.Status = PromptStatus.OK Then

                Dim acSSet As SelectionSet = acSSPrompt.Value

                acObjIdColl = New ObjectIdCollection()

                ' Part 1 collect items to merge into new drawing
                For Each acSSObj As SelectedObject In acSSet

                    If Not IsDBNull(acSSObj) Then

                        acObjIdColl.Add(acSSObj.ObjectId)

                    End If
                Next

                acTrans.Commit()

            End If

        End Using



        'Part 2 Need to change part 2 so it copys multiple parts in then saves

        Dim sLocalRoot As String = Application.GetSystemVariable("LOCALROOTPREFIX")
        Dim sTemplatePath As String = sLocalRoot + "Template\acad.dwt"
        Dim TemplatePath As String = "D:\Documents and Settings\UserName\My Documents\2011 Acad Blocks\Temp.dwg"

        Dim acDocMgr As DocumentCollection = Application.DocumentManager
        Dim acNewDoc As Document = acDocMgr.Add(sTemplatePath)
        Dim acDbNewDoc As Database = acNewDoc.Database

        Using acLckDoc As DocumentLock = acNewDoc.LockDocument()

            Using acTrans = acDbNewDoc.TransactionManager.StartTransaction()

                Dim acBlkTblNewDoc As BlockTable
                acBlkTblNewDoc = acTrans.GetObject(acDbNewDoc.BlockTableId, OpenMode.ForRead)

                Dim acBlkTblRecNewDoc As BlockTableRecord
                acBlkTblRecNewDoc = acTrans.GetObject(acBlkTblNewDoc(BlockTableRecord.ModelSpace), OpenMode.ForRead)

                ' Clone the objects to the new database
                Dim acIdMap As IdMapping = New IdMapping()
                acCurDb.WblockCloneObjects(acObjIdColl, acBlkTblRecNewDoc.ObjectId, acIdMap, DuplicateRecordCloning.Ignore, False)

                acTrans.Commit()

            End Using

        End Using

        '' Set the new document current
        acDocMgr.MdiActiveDocument = acNewDoc

        '' Regenerate the drawing
        Application.DocumentManager.MdiActiveDocument.Editor.Regen()



    End Sub

RMS

  • Guest
bump? Anyone??

Well I decided that maybe I need a new approach on this, or I may have confused all viewers of my issue by not being very clear, so sorry if that was the case.   :-o

Just to clarify, I have 4 separate .dxf files that I need to merge into 1 single file. This happens to me about 7 times a day and I have a ton of other things to do so I am trying to automate this. Right now I manually create a wblock of the part in each of the 3 files and save them, then when I am in that 4th file I then insert those 3 blocks "w/explode selected" so now I have all 4 parts in my final .dxf file all in the correct location sine I use the original x,y,z location of each.

I suppose I could learn to automate the wblock and insert functions but since these are all basic parts made up of lines I am now just thinking about doing a selection set to gather up all the line start and end points into an arraylist  then just reading the list and redrawing the lines in the destination file.

Any ideas on this?

   

   

 

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Have a play with this :
Compiled and tested in AC2012 with .NET Framework 4  in VS2010


Code: [Select]
//
// CodeHimBelonga KDUB 2011.11.13.

using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using AcUtils = Autodesk.AutoCAD.Internal.Utils;

[assembly: CommandClass(typeof (KDUB_Testing.DXF4into.MyCommands))]

namespace KDUB_Testing.DXF4into
{
    public class MyCommands
    {
        [CommandMethod("DXF4", CommandFlags.Modal | CommandFlags.Session)]
        public void DXF4Into1() {
            var doc = AcadApp.DocumentManager.MdiActiveDocument;
            var ed = doc.Editor;
            var db = doc.Database;

            string[] fnlist = SelectDXFFile();

            if (fnlist == null) {
                return;
            }
            foreach (string fn in fnlist) {
                ed.WriteMessage("\n" + fn);

                var TmpDb = new Database(false, true);
                TmpDb.DxfIn(fn, fn + ".log");
                Matrix3d Transform = Matrix3d.Identity;
                using (DocumentLock docLock = doc.LockDocument()) {
                    using (Transaction tr = doc.TransactionManager.StartTransaction()) {
                        db.Insert(Transform, TmpDb, true);
                        tr.Commit();
                    }
                }
            }
        }

        public string[] SelectDXFFile() {
            var dialog = new OpenFileDialog {
                                                CheckFileExists = true,
                                                CheckPathExists = true,
                                                DefaultExt = "dxf",
                                                DereferenceLinks = true,
                                                Filter = "DXF Files (*.dxf)|*.dxf|All files (*.*)|*.*",
                                                Title = "Select dxf file",
                                                Multiselect = true
                                            };

            if (dialog.ShowDialog() != DialogResult.OK) {
                return null;
            }
            return dialog.FileNames;
        }
    }
}
« Last Edit: November 12, 2011, 07:30:45 PM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>

This is a conversion to VB.net with SharpDevelop ... no responsibility   :laugh:

Code: [Select]
'
' CodeHimBelonga KDUB 2011.11.13.

Imports System.Windows.Forms
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Runtime

Imports AcadApp = Autodesk.AutoCAD.ApplicationServices.Application
Imports AcUtils = Autodesk.AutoCAD.Internal.Utils

<Assembly: CommandClass(GetType(KDUB_Testing.DXF4into.MyCommands))>

Namespace KDUB_Testing.DXF4into
Public Class MyCommands
<CommandMethod("DXF4", CommandFlags.Modal Or CommandFlags.Session)> _
Public Sub DXF4Into1()
Dim doc = AcadApp.DocumentManager.MdiActiveDocument
Dim ed = doc.Editor
Dim db = doc.Database

Dim fnlist As String() = SelectDXFFile()

If fnlist Is Nothing Then
Return
End If
For Each fn As String In fnlist
ed.WriteMessage(vbLf & fn)

Dim TmpDb = New Database(False, True)
TmpDb.DxfIn(fn, fn & ".log")
Dim Transform As Matrix3d = Matrix3d.Identity
Using docLock As DocumentLock = doc.LockDocument()
Using tr As Transaction = doc.TransactionManager.StartTransaction()
db.Insert(Transform, TmpDb, True)
tr.Commit()
End Using
End Using
Next
End Sub

Public Function SelectDXFFile() As String()
Dim dialog = New OpenFileDialog() With { _
Key .CheckFileExists = True, _
Key .CheckPathExists = True, _
Key .DefaultExt = "dxf", _
Key .DereferenceLinks = True, _
Key .Filter = "DXF Files (*.dxf)|*.dxf|All files (*.*)|*.*", _
Key .Title = "Select dxf file", _
Key .Multiselect = True _
}

If dialog.ShowDialog() <> DialogResult.OK Then
Return Nothing
End If
Return dialog.FileNames
End Function
End Class
End Namespace
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

RMS

  • Guest
Kerry,

That C# code worked like a charm; I was testing the C# code and then I noticed you posted VB code also! This is really going to help me big time, so thanks a ton. I will test the VB out next.......

Rob


Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>

You're most welcome Rob.

I haven't tested the validity of the VB translation :)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

RMS

  • Guest
The translator was close and all was good but the function, so I cleaned it up for any VB guy who is interested.

Quote
    Public Function SelectDXFFile() As String()

        Dim dialog = New OpenFileDialog()
        With dialog
            .CheckFileExists = True
            .CheckPathExists = True
            .DefaultExt = "dxf"
            .DereferenceLinks = True
            .Filter = "DXF Files (*.dxf)|*.dxf|All files (*.*)|*.*"
            .Title = "Select dxf file"
            .Multiselect = True
        End With
            
        If dialog.ShowDialog() <> DialogResult.OK Then
            Return Nothing
        End If
        Return dialog.FileNames
    End Function

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
May be a benefit to add a zoom at the end of the DXF4Into Method.

Code: [Select]
AcadApp.DocumentManager.MdiActiveDocument.SendStringToExecute("Zoom e\n", false, false, false);

For anyone who wants to test this here's the DLL
Load with the NETLOAD command
The command is DXF4
« Last Edit: November 12, 2011, 09:14:11 PM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

RMS

  • Guest
Kerry,

What does this line do:

Quote
TmpDb.DxfIn(fn, fn + ".log");

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
The signature is
public void DxfIn(string fileName, string logFilename)
    Member of Autodesk.AutoCAD.DatabaseServices.Database

This piccy from the ObjectARX for AutoCAD 2012 : Reference Guide    < ArxDoc.chm> may help
« Last Edit: November 12, 2011, 09:51:48 PM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

RMS

  • Guest
Re: Help with code to merge multiple Objects from 4 drawings into 1 new drawing
« Reply #10 on: November 12, 2011, 10:12:35 PM »
Creates a log file if errors occur! WOW they think of everything........ :ugly:

Thanks.


RMS

  • Guest
Re: Help with code to merge multiple Objects from 4 drawings into 1 new drawing
« Reply #11 on: September 29, 2013, 11:13:49 AM »
I would like to expand on the above code and was looking for some advice, its been a while since I did any coding.

The above code I think copies the database into a new file and it works good no issues here. My new objective now is to reposition the entities to a new location and I was wondering what would be the best option to do this?

Some facts: its all lines, and just a simple 2D file using the WCS.

I would like to elevate all the Z values to a new value of 10

Thanks for any ideas on this!

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Help with code to merge multiple Objects from 4 drawings into 1 new drawing
« Reply #12 on: September 30, 2013, 01:49:38 PM »
something like:

Code - C#: [Select]
  1. using (Transaction tr = db.TransactionManager.StartTransaction())
  2. {
  3. Matrix3d mat = new Matrix3d(Matrix3d.Displacement(new Vector3d(0,0,10)));
  4. foreach (ObjectId id in ObjectIdCollection)
  5. {
  6.    ((Entity)tr.GetObject(id, OpenMode.ForWrite)).TransformBy(mat);
  7.    
  8. }
  9. tr.Commit();
  10. }

Note, this is just written on the fly for this post and has not been tested or compiled

RMS

  • Guest
Thanks for the sample! I have not tested it yet but I will post back as soon as I do.