• Industries
  • Products
  • Buy
  • Services & Support
  • Communities
  • Discussion Groups

    .NET

    Reply
    Distinguished Contributor
    Posts: 143
    Registered: ‎07-07-2006

    VB.NET: Inserting a file (block)

    2212 Views, 6 Replies
    01-19-2009 04:02 PM
    Good evening,

    Does anyone have a code snippet that shows how to insert a drawing (as a block) into the current drawing? I searched this forum for a few samples and only found partial functions, too little for me to turn into a working function or even understand what I should attempt to do.

    I have a drawing on my hard drive and I want to insert it into my current drawing. It seems simple enough but I'm not getting it. Any suggestions?

    Thanks,
    Josh

    Windows XP SP2
    VS 2005 SP1
    AutoCAD Civil 3D 2009 SP2
    Please use plain text.
    *Joe Sutphin

    Re: VB.NET: Inserting a file (block)

    01-20-2009 06:42 AM in reply to: joshlund

    Perhaps this will help.

    Joe
    ...

        <CommandMethod("IBFF")>
    _
        Public Shared Sub
    InsertBlockFromFile()
            'get an
    editor object
            Dim ed As Editor =
    Application.DocumentManager.MdiActiveDocument.Editor

     

            'ask for
    block name from user
            Dim
    BlockNameOptions As PromptStringOptions = New PromptStringOptions("Enter block
    name")
            'no spaces allowed with
    block names
           
    BlockNameOptions.AllowSpaces =
    False
            'get the
    input
            Dim BlockNameResult As
    PromptResult = ed.GetString(BlockNameOptions)

     

            'check
    for valid input
            If
    (BlockNameResult.Status = PromptStatus.OK)
    Then
                'get
    the working
    database
               
    Dim dwg As Database =
    ed.Document.Database
               
    'start a
    transaction
               
    Dim ta As Transaction = dwg.TransactionManager.StartTransaction

     


    size=2>           
    Try
                   
    'create temporary database to read in
    block
                   
    Dim dbDwg As New
    Database()
                   
    'read the file from
    disk
                   
    dbDwg.ReadDwgFile("C:\Drawing2.dwg", IO.FileShare.Read, True,
    "")
                   
    'insert it into the current
    database
                   
    dwg.Insert(BlockNameResult.StringResult.ToString, dbDwg,
    False)
                   
    'dispose of temporary database
    object
                   
    dbDwg.Dispose()

     


    size=2>               
    'open the block table for
    read
                   
    Dim BlockTable As BlockTable = ta.GetObject(dwg.BlockTableId,
    OpenMode.ForRead)

     


    size=2>               
    'see if the block table record
    exists
                   
    If (BlockTable.Has(BlockNameResult.StringResult) = True)
    Then
                       
    'prompt user for insertion
    point
                       
    Dim PromptPointOptions As PromptPointOptions = New PromptPointOptions("Select
    insertion
    point")
                       
    'get user to select the insertion
    point
                       
    Dim PromptPointResult As PromptPointResult =
    ed.GetPoint(PromptPointOptions)

     


    size=2>                   
    'user selected a valid
    point
                       
    If (PromptPointResult.Status = PromptStatus.OK)
    Then
                           
    'fix up the point to be a Point3D
    object
                           
    Dim Point3D As New Point3d(PromptPointResult.Value.X, PromptPointResult.Value.Y,
    PromptPointResult.Value.Z)

     


    size=2>                       
    'insert the block at the insertion
    point
                           
    Dim BlockRef As BlockReference = New BlockReference(Point3D,
    BlockTable.Item(BlockNameResult.StringResult))

     


    size=2>                       
    'add block reference to the current
    space
                           
    Dim CurrentSpace As BlockTableRecord = ta.GetObject(dwg.CurrentSpaceId,
    OpenMode.ForWrite)

     


    size=2>                       
    'add the block reference to the current
    space
                           
    CurrentSpace.AppendEntity(BlockRef)

     


    size=2>                       
    'tell the
    transaction
                           
    ta.AddNewlyCreatedDBObject(BlockRef, True)

     


    size=2>                       
    'commit transaction to
    database
                           
    ta.Commit()

     


    size=2>                   
    End If

     


    size=2>               
    Else
                       
    MsgBox("Block " & BlockNameResult.StringResult.ToString & " does not
    exists")

     


    size=2>               
    End If

     


    size=2>            Catch
    ex As
    Exception
                   
    MsgBox(ex.Message)

     


    size=2>           
    Finally

     


    size=2>               
    'always dispose of
    transaction
                   
    ta.Dispose()

     


    size=2>            End
    Try
            End If
       
    End Sub
    <JoshLund> wrote in message
    news:6107709@discussion.autodesk.com...
    Good evening, Does anyone have a code
    snippet that shows how to insert a drawing (as a block) into the current
    drawing? I searched this forum for a few samples and only found partial
    functions, too little for me to turn into a working function or even understand
    what I should attempt to do. I have a drawing on my hard drive and I want to
    insert it into my current drawing. It seems simple enough but I'm not getting
    it. Any suggestions? Thanks, Josh Windows XP SP2 VS 2005 SP1 AutoCAD Civil 3D
    2009 SP2
    Please use plain text.
    Distinguished Contributor
    Posts: 143
    Registered: ‎07-07-2006

    Re: VB.NET: Inserting a file (block)

    01-20-2009 08:48 AM in reply to: joshlund
    Joe,

    Let me start out by saying thanks for such an excellent example. It is well commented and easy to follow.

    When I first ran the code, it threw a FileNotFound exception. Not sure where "C:\Drawing2.dwg" was coming from I changed it to the name of the block I wanted to insert. This cleared up that exception. Not sure if that was the right thing to do as I encountered another problem a short time later.

    'read the file from disk
    'dbDwg.ReadDwgFile("C:\Drawing2.dwg", IO.FileShare.Read, True, "")

    was changed to. . .

    dbDwg.ReadDwgFile(BlockNameResult.StringResult.ToString, IO.FileShare.Read, True, "")


    I ran it again and the following line threw an OutOfRange exception.

    dwg.Insert(BlockNameResult.StringResult.ToString, dbDwg, False)

    I tried a few things to fix this but can't seem to find the answer. Some things I tried: I changed BlockNameResult.StringResult.ToString to a static string, just to see if it would work. I tried specifying the block name with a full path and without a full path, thinking the path may have been causing the outof range exception.

    The class file is attached as Class1.txt. Any suggestions?

    Thanks,
    Josh
    Please use plain text.
    *Tony Tanzillo

    Re: VB.NET: Inserting a file (block)

    01-20-2009 12:24 PM in reply to: joshlund
    Sorry to say, but we can't call that an 'excellent' example.

    Joe's code (assuming he actually wrote it, that is) converts the user's
    coordinate into a Point3d. Problem is, it's
    already a Point3d, making that pointless and unnecessary.

    The code he posted also needlessly looks up the objectid of the
    newly-inserted BlockTableRecord, when that is what is returned by the
    Insert() method, whose result his code completely ignores.

    So no, we can't call that an 'excellent' example.

    My suggestion would be to focus on learning the language and the API. For
    example, you call the 'ToString()' method on an object that is already a
    string. If the object is already a string, you don't have to convert it to a
    string. But it is the fact that you do not know that the object is already a
    string, that suggests that you're trying to run before having learned to
    walk, and that's the core problem you're faced with. No matter how good the
    examples you find here are, they're not going to help you that much if you
    don't understand the code, or how to modify/adapt them to your particular
    situation.

    If you are going to use VB.NET and the ObjectARX API, you have to learn to
    use the programming language; the .NET framework, and the AutoCAD .NET API,
    in that order.

    The example below is in C#, but you can convert it to VB.NET using various
    online translators or Reflector.

    [code]

    {code}

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Windows.Forms;
    using Autodesk.AutoCAD.Runtime;
    using Autodesk.AutoCAD.DatabaseServices;
    using Autodesk.AutoCAD.Geometry;
    using Autodesk.AutoCAD.EditorInput;
    using Autodesk.AutoCAD.ApplicationServices;

    using Acad = Autodesk.AutoCAD.ApplicationServices.Application;

    [assembly: CommandClass(typeof( Namespace1.InsertBlockFromFileExample ))]

    namespace Namespace1
    {
    public static class InsertBlockFromFileExample
    {
    [CommandMethod("XINSERT")]
    public static void InsertFromFileCommand()
    {
    OpenFileDialog ofd = new OpenFileDialog();
    ofd.DefaultExt = ".dwg";
    ofd.Filter = "Drawing Files (*.dwg)|*.dwg";
    if( ofd.ShowDialog( Acad.MainWindow ) != DialogResult.OK )
    return;
    Document doc = Acad.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;
    Editor ed = doc.Editor;
    PromptPointOptions ppo = new PromptPointOptions( "\nInsertion
    point: " );
    PromptPointResult ppr = ed.GetPoint( ppo );
    if( ppr.Status != PromptStatus.OK )
    return;
    using( Database xDb = new Database( false, true ) )
    {
    xDb.ReadDwgFile( ofd.FileName, FileShare.Read, true, null );
    using( Transaction tr =
    doc.TransactionManager.StartTransaction() )
    {
    string name =
    SymbolUtilityServices.GetBlockNameFromInsertPathName( ofd.FileName );
    ObjectId id = db.Insert( name, xDb, true );
    if( id.IsNull )
    {
    ed.WriteMessage( "\nFailed to insert block" );
    return;
    }
    BlockTableRecord currSpace = tr.GetObject( db.CurrentSpaceId,
    OpenMode.ForWrite ) as BlockTableRecord;
    BlockReference insert = new BlockReference( ppr.Value, id );
    currSpace.AppendEntity( insert );
    insert.SetDatabaseDefaults();
    tr.AddNewlyCreatedDBObject( insert, true );
    tr.Commit();
    }
    }
    }
    }
    }


    {code}

    [/code]

    --
    http://www.caddzone.com

    AcadXTabs: MDI Document Tabs for AutoCAD 2009
    Supporting AutoCAD 2000 through 2009
    http://www.acadxtabs.com

    Introducing AcadXTabs 2010:
    http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


    wrote in message news:6108224@discussion.autodesk.com...
    Joe, Let me start out by saying thanks for such an excellent example. It is
    well commented and easy to follow. When I first ran the code, it threw a
    FileNotFound exception. Not sure where "C:\Drawing2.dwg" was coming from I
    changed it to the name of the block I wanted to insert. This cleared up that
    exception. Not sure if that was the right thing to do as I encountered
    another problem a short time later. 'read the file from disk
    'dbDwg.ReadDwgFile("C:\Drawing2.dwg", IO.FileShare.Read, True, "") was
    changed to. . . dbDwg.ReadDwgFile(BlockNameResult.StringResult.ToString,
    IO.FileShare.Read, True, "") I ran it again and the following line threw an
    OutOfRange exception. dwg.Insert(BlockNameResult.StringResult.ToString,
    dbDwg, False) I tried a few things to fix this but can't seem to find the
    answer. Some things I tried: I changed BlockNameResult.StringResult.ToString
    to a static string, just to see if it would work. I tried specifying the
    block name with a full path and without a full path, thinking the path may
    have been causing the outof range exception. The class file is attached as
    Class1.txt. Any suggestions? Thanks, Josh
    Please use plain text.
    *Roland Feletic

    Re: VB.NET: Inserting a file (block)

    01-21-2009 05:23 AM in reply to: joshlund
    Thank you, Tony.
    This code works really great, as allways. I hope you don't mind that I
    changed the code a little bit that it works with annotative blocks, too.
    Don't forget to set a reference to acmgdinternal.

    [code]

    {code}
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Windows.Forms;
    using Autodesk.AutoCAD.Runtime;
    using Autodesk.AutoCAD.DatabaseServices;
    using Autodesk.AutoCAD.Geometry;
    using Autodesk.AutoCAD.EditorInput;
    using Autodesk.AutoCAD.ApplicationServices;
    using Autodesk.AutoCAD.Internal;

    using Acad = Autodesk.AutoCAD.ApplicationServices.Application;

    [assembly: CommandClass(typeof( RSNNAcadApp.Test.InsertBlock_Tanzillo ))]
    namespace RSNNAcadApp.Test
    {
    class InsertBlock_Tanzillo
    {
    [CommandMethod("XINSERT")]
    public static void InsertFromFileCommand()
    {
    OpenFileDialog ofd = new OpenFileDialog();
    ofd.DefaultExt = ".dwg";
    ofd.Filter = "Drawing Files (*.dwg)|*.dwg";
    if (ofd.ShowDialog(Acad.MainWindow) != DialogResult.OK)
    return;
    Document doc = Acad.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;
    Editor ed = doc.Editor;
    PromptPointOptions ppo = new PromptPointOptions("\nEinsetzpunkt:
    ");
    PromptPointResult ppr = ed.GetPoint(ppo);
    if (ppr.Status != PromptStatus.OK)
    return;
    using (Database xDb = new Database(false, true))
    {
    xDb.ReadDwgFile(ofd.FileName, FileShare.Read, true, null);

    using (Transaction tr =
    doc.TransactionManager.StartTransaction())
    {
    string name =
    SymbolUtilityServices.GetBlockNameFromInsertPathName(ofd.FileName);
    ObjectId id = db.Insert(name, xDb, true);
    if (id.IsNull)
    {
    ed.WriteMessage("\nFailed to insert block");
    return;
    }

    //for inserting an annotative dwg
    if (xDb.AnnotativeDwg)
    {
    using (BlockTableRecord btrAnnotative =
    (BlockTableRecord)tr.GetObject(id, OpenMode.ForWrite))
    {
    btrAnnotative.Annotative =
    AnnotativeStates.True;
    }
    }

    BlockTableRecord currSpace =
    tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
    BlockReference insert = new BlockReference(ppr.Value,
    id);
    currSpace.AppendEntity(insert);
    insert.SetDatabaseDefaults();

    //for inserting an annotative dwg
    if (xDb.AnnotativeDwg)
    {
    //Attach Current Annotation-Scale.
    //If you don't add the content, the block and the
    following attribute will not inserted correct.
    ObjectContextManager ocm = db.ObjectContextManager;
    ObjectContextCollection occ =
    ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");
    ObjectContexts.AddContext(insert,
    occ.CurrentContext);
    }

    tr.AddNewlyCreatedDBObject(insert, true);
    tr.Commit();
    }
    }
    }
    }
    }
    {code}

    [/code]
    Please use plain text.
    *Tony Tanzillo

    Re: VB.NET: Inserting a file (block)

    01-21-2009 12:43 PM in reply to: joshlund
    Glad it worked for you, and thanks for posting
    your enhancement. I'm sure others might find it useful.

    --
    http://www.caddzone.com

    AcadXTabs: MDI Document Tabs for AutoCAD 2009
    Supporting AutoCAD 2000 through 2009
    http://www.acadxtabs.com

    Introducing AcadXTabs 2010:
    http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


    "Roland Feletic" wrote in message
    news:6108849@discussion.autodesk.com...
    Thank you, Tony.
    This code works really great, as allways. I hope you don't mind that I
    changed the code a little bit that it works with annotative blocks, too.
    Don't forget to set a reference to acmgdinternal.

    [code]

    {code}
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Windows.Forms;
    using Autodesk.AutoCAD.Runtime;
    using Autodesk.AutoCAD.DatabaseServices;
    using Autodesk.AutoCAD.Geometry;
    using Autodesk.AutoCAD.EditorInput;
    using Autodesk.AutoCAD.ApplicationServices;
    using Autodesk.AutoCAD.Internal;

    using Acad = Autodesk.AutoCAD.ApplicationServices.Application;

    [assembly: CommandClass(typeof( RSNNAcadApp.Test.InsertBlock_Tanzillo ))]
    namespace RSNNAcadApp.Test
    {
    class InsertBlock_Tanzillo
    {
    [CommandMethod("XINSERT")]
    public static void InsertFromFileCommand()
    {
    OpenFileDialog ofd = new OpenFileDialog();
    ofd.DefaultExt = ".dwg";
    ofd.Filter = "Drawing Files (*.dwg)|*.dwg";
    if (ofd.ShowDialog(Acad.MainWindow) != DialogResult.OK)
    return;
    Document doc = Acad.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;
    Editor ed = doc.Editor;
    PromptPointOptions ppo = new PromptPointOptions("\nEinsetzpunkt:
    ");
    PromptPointResult ppr = ed.GetPoint(ppo);
    if (ppr.Status != PromptStatus.OK)
    return;
    using (Database xDb = new Database(false, true))
    {
    xDb.ReadDwgFile(ofd.FileName, FileShare.Read, true, null);

    using (Transaction tr =
    doc.TransactionManager.StartTransaction())
    {
    string name =
    SymbolUtilityServices.GetBlockNameFromInsertPathName(ofd.FileName);
    ObjectId id = db.Insert(name, xDb, true);
    if (id.IsNull)
    {
    ed.WriteMessage("\nFailed to insert block");
    return;
    }

    //for inserting an annotative dwg
    if (xDb.AnnotativeDwg)
    {
    using (BlockTableRecord btrAnnotative =
    (BlockTableRecord)tr.GetObject(id, OpenMode.ForWrite))
    {
    btrAnnotative.Annotative =
    AnnotativeStates.True;
    }
    }

    BlockTableRecord currSpace =
    tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
    BlockReference insert = new BlockReference(ppr.Value,
    id);
    currSpace.AppendEntity(insert);
    insert.SetDatabaseDefaults();

    //for inserting an annotative dwg
    if (xDb.AnnotativeDwg)
    {
    //Attach Current Annotation-Scale.
    //If you don't add the content, the block and the
    following attribute will not inserted correct.
    ObjectContextManager ocm = db.ObjectContextManager;
    ObjectContextCollection occ =
    ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");
    ObjectContexts.AddContext(insert,
    occ.CurrentContext);
    }

    tr.AddNewlyCreatedDBObject(insert, true);
    tr.Commit();
    }
    }
    }
    }
    }
    {code}

    [/code]
    Please use plain text.
    Contributor
    Posts: 11
    Registered: ‎11-13-2006

    Re: VB.NET: Inserting a file (block)

    05-11-2010 10:41 AM in reply to: joshlund
    Tony, I appreciate you posting this code and providing the solution. I found it to be helpful to me, and really didn't have much pain in converting it to vb.net and getting it to fit into my existing class.

    I'm hoping to be able to tweak it so that rather than using the file dialog, that it would use a specific file that is identified as part of another sub in an "IF....THEN" statement. I don't know if that's possible, but I guess I'll find out. :smileywink:

    Thanks again. Very helpful.
    Please use plain text.