View Full Version : How to insert a DWG file as a block
Coolmo
2009-09-18, 03:13 PM
I've been reading up on how to insert a block into the current drawing from a drawing file (Filename.DWG) but the examples give an actual path for the file. If you leave the path off of the file name does it automatically search through your file search path list? I think VBA does this.
The examples I'm finding online for how to insert a file as a block are sketchy at best and some of the members actually argue back and forth about who's got the better way and who's code is sloppy, etc.
If this is an easy task, can someone post some code to show me how to do this? It doesn't have to be extensive code with all the transaction stuff involved. Just the few lines I'll need to do this assuming that I have a block name in mind and have already obtained a point3d and scale variable (if needed)
ANY help is very appreciated. Thanks
T.Willey
2009-09-18, 04:03 PM
public static ObjectId InsertBlock ( Database db, string loName, string blkName, Point3d insPt ) {
ObjectId RtnObjId = ObjectId.Null;
using ( Transaction Trans = db.TransactionManager.StartTransaction( ) ) {
DBDictionary LoDict = Trans.GetObject( db.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
foreach ( DictionaryEntry de in LoDict ) {
if ( string.Compare( ( string )de.Key, loName, true ).Equals( 0 ) ) {
Layout Lo = Trans.GetObject( ( ObjectId )de.Value, OpenMode.ForWrite ) as Layout;
BlockTable BlkTbl = Trans.GetObject( db.BlockTableId, OpenMode.ForRead ) as BlockTable;
BlockTableRecord LoRec = Trans.GetObject( Lo.BlockTableRecordId, OpenMode.ForRead ) as BlockTableRecord;
ObjectId BlkTblRecId = GetNonErasedTableRecordId( BlkTbl.Id, blkName );
if ( BlkTblRecId.IsNull ) {
string BlkPath = HostApplicationServices.Current.FindFile( blkName + ".dwg", db, FindFileHint.Default );
if ( string.IsNullOrEmpty( BlkPath ) )
return RtnObjId;
BlkTbl.UpgradeOpen( );
using ( Database tempDb = new Database( false, true ) ) {
tempDb.ReadDwgFile( BlkPath, FileShare.Read, true, null );
db.Insert( blkName, tempDb, false );
}
BlkTblRecId = GetNonErasedTableRecordId( BlkTbl.Id, blkName );
}
LoRec.UpgradeOpen( );
BlockReference BlkRef = new BlockReference( insPt, BlkTblRecId );
LoRec.AppendEntity( BlkRef );
Trans.AddNewlyCreatedDBObject( BlkRef, true );
BlockTableRecord BlkTblRec = Trans.GetObject( BlkTblRecId, OpenMode.ForRead ) as BlockTableRecord;
if ( BlkTblRec.HasAttributeDefinitions ) {
foreach ( ObjectId objId in BlkTblRec ) {
AttributeDefinition AttDef = Trans.GetObject( objId, OpenMode.ForRead ) as AttributeDefinition;
if ( AttDef != null ) {
AttributeReference AttRef = new AttributeReference( );
AttRef.SetAttributeFromBlock( AttDef, BlkRef.BlockTransform );
BlkRef.AttributeCollection.AppendAttribute( AttRef );
Trans.AddNewlyCreatedDBObject( AttRef, true );
}
}
}
Trans.Commit( );
}
}
}
return RtnObjId;
}
This is my sub...... ' GetNonErasedTableRecordId ' is Tony T.'s code, so you might have to search for it, but it does just what the title says.
Coolmo
2009-09-18, 06:15 PM
Thanks for the code. Is that in C#? Is there a VB.NET equivalent or is it basically the same idea? It looks a little more complicated than I thought. It also appears to handle blocks with attributes too. Is that correct?
T.Willey
2009-09-18, 06:50 PM
It is C#, and it should be about the same in VB, as far as calls go. Yes it does handle blocks with attributes. It will also find blocks that are not in the drawing, but are in the search path.
T.Willey
2009-09-21, 03:16 PM
Tony,
No offense taken. Most likely in-experience. When I wrote that it had to work with .Net1.1, so I don't know if those items were available then, but if they were I didn't notice them, or I would like to think that I would have used them.
Coolmo
2009-09-24, 07:47 PM
I'm using VB.Net BTW...
Alright, I have the insertion of the block working but I still had to hardwire the path into the code. When I tried to simply put the drawing name in ("drawing.DWG") it comes back with an error and the block is not inserted. The "drawing.DWG" file it's trying to insert is in the AutoCAD support directory so I know it's in the search path. Of course when I move the file to a specific directory and add this path in front of the drawing name it inserts perfectly. What am I missing?
Also, I couldn't follow how the attribute portion of the code was working (from your response) and what it was suppose to do. I tried inserting a block with attributes into my drawing (with the hard wired path from above) and it inserted but the attributes completely disappeared from the block. I couldn't even edit the attributes in the inserted block because AutoCAD came back with "There are no editable attributes in the selected block". The weird thing is when I inserted the same block using normal AutoCAD INSERT, the block inserts and prompts me for the attribute values and so on. It kinda freaked me out seeing the very same block staring at me on the screen where one has the original attribute and the other can't find them. Anyway...
My task here is to insert the block from a file and then set the attribute(s) inside the block during this insert. Can someone point me in the right direction for the attribute portion of this? In VB.Net preferably? Thanks for all the help so far. I'm almost there.
Coolmo
2009-10-02, 08:32 PM
I got it now. It's tough trying to find answers to even the simplest of questions on the internet because everyone does things a slightly different way. They all probably work but with all the different methods out there it's hard to piece together what you really need to cut outta the code to use.... and understand...
Anyway, so it turns out that it's pretty easy. After the block (reference) is inserted you query the blocktable for a record with the same name as your block name, test to see if it has attributes and if so, then append those attributes back into the new block reference you just created. Then you set all the attribute text from there.
My block also has dynamic properties so I get to dive into that one tonight. :beer: With lots of beer of course.
clintonc
2010-06-21, 10:17 PM
how did that dynamic portion of the code go? I would love to see the code you came up with. I am tring to learn how to insert a block with .net
Coolmo
2010-06-22, 01:36 AM
how did that dynamic portion of the code go? I would love to see the code you came up with. I am tring to learn how to insert a block with .net
I'm working with and inserting one of my own blocks with Dynamic block properties so it was easy to manipulate the dynamic properties because I know what the property names are (Position1 X, Position1 Y, etc) After the block is inserted you just go through each dynamic property, match the property name to the one you want to change and then reset its value. Of course the NewXValue and NewYValue are declared and set earlier in the program to whatever I want them to be...
Dim BlockRef As BlockReference = New BlockReference(Point3D, BlockTable.Item(Filenamewhat))
Dim DynProp As DynamicBlockReferenceProperty
For Each DynProp In BlockRef.DynamicBlockReferencePropertyCollection
If DynProp.PropertyName = "Position1 X" Then
DynProp.Value = NewXValue
End If
If DynProp.PropertyName = "Position1 Y" Then
DynProp.Value = NewYValue
End If
Next
This allows me to insert specific blocks with all kinds of dynamic properties associated with them and set the dynamic properties on the fly using the .NET user interface (i.e. my dialog box with specific options pertaining to the dynamic block). Works great.
This is also useful in a "Civil3D" like program I'm writing that uses dynamic blocks with attributes that allows the user to import XML files from Hydraflow that interact with all the blocks (my dynamic blocks) already in the drawing (plan and profile) and moves them around on the screen to their correct location in plan viiew and in the profile, labeling as it goes... very cool to watch happen on screen.
Powered by vBulletin® Version 4.1.11 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.