.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Trying to insert a block with C#

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
sonny3g
12551 Views, 6 Replies

Trying to insert a block with C#

I am trying to insert a block that will not initially exist in the current drawing, but once inserted may be inserted multiple times.  I have code that determines the name of the block and the insertion point I need to insert from a directory and returns the block name to the routine that will insert the block.  It appears to work, except that the block never shows up.  I don't know what I am missing and could some suggestions.

 class BlockInsert
    {
        public void InsertBlock(AcGeo.Point3d InsPt, string BlkName)
        {
            AppSvc.Document cDoc = App.DocumentManager.MdiActiveDocument;
            DBSvc.Database cDB = cDoc.Database;
            AcEdIn.Editor cEd = cDoc.Editor;

            using (DBSvc.Transaction Trans1 = cDB.TransactionManager.StartTransaction())
            {
                DBSvc.BlockTable blkTable;
                blkTable = Trans1.GetObject(cDB.BlockTableId, DBSvc.OpenMode.ForWrite) as DBSvc.BlockTable;
                DBSvc.BlockTableRecord blkTableRec = new DBSvc.BlockTableRecord();
                if (!blkTable.Has(BlkName))
                {
                    blkTable.Add(blkTableRec);
                    Trans1.AddNewlyCreatedDBObject(blkTableRec, true);
                    blkTableRec.Name = BlkName;
                }
                // Insert support block at insertion point InsPt
                DBSvc.BlockTableRecord space = (DBSvc.BlockTableRecord)Trans1.GetObject(cDB.CurrentSpaceId, DBSvc.OpenMode.ForWrite);
                DBSvc.BlockReference rfml = new DBSvc.BlockReference(InsPt, blkTableRec.ObjectId);
                space.AppendEntity(rfml);
                Trans1.AddNewlyCreatedDBObject(rfml, true);
                Trans1.Commit();
            }
            MessageBox.Show("\nThe block name is: " + BlkName, "BlockName", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
        }
    }
Scott G. Sawdy
scott.sawdy@bluecoyotecad.com
6 REPLIES 6
Message 2 of 7
_gile
in reply to: sonny3g

Hi,

 

The code you show should work, but it creates an empty block, this is why you can't see it.

 

You can use this overload of the Database.Insert() method to add a new BlockTableRecord in the BlockTable containing the entities of the source database model space.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 7
sonny3g
in reply to: _gile

Thanks for the reply and help Giles. Unfortunately, I am not a good enough programmer to understand how to implement your suggestion in my program.  I am really just a dabbler being tasked with improving over our current crop of LISP programs.

Scott G. Sawdy
scott.sawdy@bluecoyotecad.com
Message 4 of 7
_gile
in reply to: sonny3g

Try this:

 

        public void InsertBlock(Point3d insPt, string blockName)
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                // check if the block table already has the 'blockName'" block
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (!bt.Has(blockName))
                {
                    try
                    {
                        // search for a dwg file named 'blockName' in AutoCAD search paths
                        var filename = HostApplicationServices.Current.FindFile(blockName + ".dwg", db, FindFileHint.Default);
                        // add the dwg model space as 'blockName' block definition in the current database block table
                        using (var sourceDb = new Database(false, true))
                        {
                            sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, true, "");
                            db.Insert(blockName, sourceDb, true);
                        }
                    }
                    catch
                    {
                        ed.WriteMessage($"\nBlock '{blockName}' not found.");
                        return;
                    }
                }

                // create a new block reference
                using (var br = new BlockReference(insPt, bt[blockName]))
                {
                    var space = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                    space.AppendEntity(br);
                    tr.AddNewlyCreatedDBObject(br, true);
                }
                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 7
sonny3g
in reply to: _gile

Thank you Gilles, that did the trick.  I am going to dig into your code to make sure I understand what you did.  Seeing working code and trying to adapt it to my needs seems to be the best way for me to learn how to write better code.

 

Thanks again!!

Scott G. Sawdy
scott.sawdy@bluecoyotecad.com
Message 6 of 7
sonny3g
in reply to: _gile

Giles,

The code you sent me for inserting blocks has been working flawlessly and I am very grateful for your help.

 

Now, though, I need to modify your code so that if the block already exists in the block table, it will deepclone the existing block instead of inserting a new one or copying the existing one.  I figured by extending your

"if (!blkTable.Has(BlkName))" statement with an else statement I would be able to excute the deepclone command instead of inserting the block.

So far, I replaced your original code:

 

  create a new block reference

  using (var br = new DBSvc.BlockReference(InsPt, blkTable[BlkName])){

  var space = (DBSvc.BlockTableRecord)Trans1.GetObject(cDB.CurrentSpaceId, DBSvc.OpenMode.ForWrite);

 

  space.AppendEntity(br);

  Trans1.AddNewlyCreatedDBObject(br, true);}

 

with this:

 

  else

  {

   DBSvc.IdMapping dupMap = new DBSvc.IdMapping();

   DBSvc.BlockTableRecord dupBTR = blkTableRec.DeepClone(blkTable, dupMap, true);

   dupBTR.Name = "duplicate";

     blkTable.Add(dupBTR);

   Trans1.AddNewlyCreatedDBObject(dupBTR, true);

  }

 

Unfortunately it does not work.  Any help is appreciated.

Scott G. Sawdy
scott.sawdy@bluecoyotecad.com
Message 7 of 7
_gile
in reply to: sonny3g

Hi,

 

It looks like you're confusing BlockTableRecord (i.e. a block definition which belongs to the BlockTable) and BlockReference (i.e. one or more inserted references in some space or other BlockTableRecord).

You can read this topic and the related ones.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report