How to include extension dictionary in block inserted using ReadDwgFile

How to include extension dictionary in block inserted using ReadDwgFile

Anonymous
Not applicable
1,472 Views
14 Replies
Message 1 of 15

How to include extension dictionary in block inserted using ReadDwgFile

Anonymous
Not applicable

Hello,

I'm inserting a block using ReadDwgFile(). The block has an extension dictionary which I want to preserve in the inserted block.

If I do it manually , for example, by dragging it from Design Center into Model Space, when I look at the block definition in the block table (using MgdDbg) the extension dictionary is there, which is what I want. When I try it in code the extension dictionary is not included.

 

Here's the code I am using.

 

using (Database sideDb = new Database(false, true))
{
   sideDb.ReadDwgFile(blkFile,FileOpenMode.OpenForReadAndReadShare, true, "");
   newObjectId = targetDb.Insert(Path.GetFileNameWithoutExtension(blkFile), sideDb, false);
}

 

What can I do to improve it to get the desired result?

Thanks

Craig

 

 

 

0 Likes
Accepted solutions (1)
1,473 Views
14 Replies
Replies (14)
Message 2 of 15

_gile
Consultant
Consultant

Hi,

 

when you say:

"I'm inserting a block using ReadDwgFile(). The block has an extension dictionary which I want to preserve in the inserted block."

 

Do you mean the Dwg file model space has an extension dictionary or the Dwg file contains a block definition which has an extension dictionary ?

 

The Database.Insert() method copies all the Model Space entities in the source database to a new BlockTableRecord in the target database BlockTable.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 15

Mikko
Advocate
Advocate
Your not telling the code to return the full path....

maybe something like: IO.Path.GetFullPath(bla bla bla) would work
0 Likes
Message 4 of 15

Anonymous
Not applicable

The file name was different to the block name so on insert I got two block table entries. One for filename and one for blockname. The entry for blockname had the extension dictionary, the entry for filename did not. The block reference in model space referred to the filename entry so no extension dictionary. (I'm listening for ObjectAppended and copy the extension dictionary from the block table entry to the block reference but the name was not expected so it did not get copied).

 

To overcome this manually using INSERT, I'd select my file, change the block name to blockname and opt to explode then I get a single block table entry, the block reference refers to blockname and my ObjectAppended handler copies the extension dictionary successfully.

 

So how to I replicate that in code?

 

I changed the insert line to use blockname instead of the filename but I get a self-reference error (which also occurs manually if you don't explode).

newObjectId = targetDb.Insert("blockname", sideDb, false);

 

I guess I need to tell it to explode it before calling insert somehow.

 

 

0 Likes
Message 5 of 15

Mikko
Advocate
Advocate
just a thought that if you have a drawing with a block in it you could do something like this which would insert the block from an external drawing into your current drawing.

Public Sub BlockGrabber(ByVal whatDwg As String, ByVal whichBlock As String)
Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
Dim db As Database = New Database()
db.ReadDwgFile(whatDwg, System.IO.FileShare.ReadWrite, True, "")
Dim ids As ObjectIdCollection = New ObjectIdCollection()
Using tr As Transaction = db.TransactionManager.StartTransaction()
Dim bt As BlockTable
bt = CType(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
Try
ids.Add(bt(whichBlock))
Catch
tr.Commit()
Return
End Try
Dim destdb As Database = ed.Document.Database
Dim iMap As IdMapping = New IdMapping()
db.WblockCloneObjects(ids, destdb.BlockTableId, iMap, DuplicateRecordCloning.Ignore, False)
tr.Commit()
End Using
End Sub
0 Likes
Message 6 of 15

_gile
Consultant
Consultant

If I don't misundertand you try to import a block which exists in another file.

if so, I do not think Databse.Insert() is the good route. as I said Databse.Insert() creates a new BlockTableRecord in the Database BlockTable which contains all the entites in the model space of the source file, so you block in the source file is a block reference nested in the newly created BlockTablerecord.

 

If you want to import only the block from the external file, you may use WblockCloneObjects().



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 15

_gile
Consultant
Consultant
Accepted solution

Here's a little sample:

 

        private ObjectId ImportBlock(string fileName, string blockName)
        {
            if (!File.Exists(fileName))
                throw new FileNotFoundException("File not found", fileName);

            Database targetDb = HostApplicationServices.WorkingDatabase;
            ObjectId owner = targetDb.BlockTableId;

            using (Database sourceDb = new Database())
            {
                sourceDb.ReadDwgFile(fileName, System.IO.FileShare.Read, false, "");
                using (Transaction tr = sourceDb.TransactionManager.StartOpenCloseTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                    if (!bt.Has(blockName))
                        return ObjectId.Null;

                    ObjectId id = bt[blockName];
                    ObjectIdCollection ids = new ObjectIdCollection();
                    ids.Add(id);
                    IdMapping idMap = new IdMapping();
                    sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Replace, false);
                    return idMap[id].IsCloned ? idMap[id].Value : ObjectId.Null;
                }
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 8 of 15

Anonymous
Not applicable

Thank you for the sample. WblockCloneObjects is new to me and I have learnt something useful. 

 

Only one issue I have now is if the source database is created using the default constructor I get eBrokenHandle error from WblockCloneObjects.

 

If I use the alternative constructor, new Database(false, true) , when I add a block reference using the new block it is drawn 25.4 times greater in size. I've checked the units in both the block's drawing and the target drawing; both set to millimeters. If I change both to unitless and set insertion default unit to millimeters I get the same result. When manually using INSERT, scale is left at 1,1,1, it is drawn at the correct size.

 

I tried setting source database Insunits to 0 but that made no difference.

 

There may be more thatn a single issue here.

 

 

 

 

0 Likes
Message 9 of 15

_gile
Consultant
Consultant

You say you checked the drawings units, but did you checked the block definition units ?



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 10 of 15

Anonymous
Not applicable

I have now. It is Milimeters.

0 Likes
Message 11 of 15

_gile
Consultant
Consultant

Could you post a drawing sample ?



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 12 of 15

Anonymous
Not applicable

Yes. Block drawing attached.

 

0 Likes
Message 13 of 15

_gile
Consultant
Consultant

Nothing wrong.

 

In the drawing you posted the block reference is scaled to 0.03937 which is equal to 1 / 25.4 (1" = 25.4 mm).



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 14 of 15

Anonymous
Not applicable

Yes, indeed, on the block reference. I did make the link between 1 inch = 25.4 mm. 

 

It must be me expecting it to be smaller when imported but the scale factor is not applied and is drawn correctly at 1:1. 

 

I'll look into how to get the scaling back to 1 in the block drawing and see if that cures it.

 

 

0 Likes
Message 15 of 15

Anonymous
Not applicable

Gilles and Mikko

Thank you both for making me aware of WblockCloneObjects.

 

I'll mark Gilles post as the answer for the follow through.

 

The scale issue was something else besides.

 

Cheers

Craig

0 Likes