Here is the complete code of both the import method and the helper class.
I´m using a wrapper for the transaction to ease some transaction operations. See code below...
public static void ImportBlocks(string filePath)
{
Document dwg = Utils.Db.GetCurDocument(); //get document
Database db = dwg.Database;
Database dbImport = new Database(false, true);
try
{
dbImport.ReadDwgFile(filePath, System.IO.FileShare.Read, true, "");
ObjectIdCollection blockIds = new ObjectIdCollection();
DocumentLock dwgLock = dwg.LockDocument(); //lock dwg
using (TransactionHelper trHlp = new TransactionHelper(dbImport))
{
trHlp.Start();
BlockTable bt = (BlockTable)trHlp.GetObject(dbImport.BlockTableId,OpenMode.ForRead);
foreach (ObjectId id in bt)
{
BlockTableRecord btr = (BlockTableRecord)trHlp.GetObject(id, OpenMode.ForRead);
if (!btr.IsAnonymous && !btr.IsLayout)
{
blockIds.Add(id);
}
btr.Dispose();
}
IdMapping mapping = new IdMapping();
dbImport.WblockCloneObjects(blockIds, db.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
trHlp.Commit();
}//disposing...
dwgLock.Dispose();
AcadUi.PrintToCmdLine("\nImported " + blockIds.Count.ToString() + " block definitions");
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
dwg.Editor.WriteMessage("\nError during import. Info: " + e.Message); //error info
}
}
using System;
using System.Diagnostics;
using System.Collections;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
namespace AcDbHelper
{
public class TransactionHelper : IDisposable
{
private Database db = null;
protected Database Db
{
get { return db; }
set { db = value; }
}
private Transaction trans = null;
protected Transaction Trans
{
get { return trans; }
set { trans = value; }
}
public
TransactionHelper()
{
Db = Utils.Db.GetCurDwg();
}
public
TransactionHelper(Database db)
{
Db = db;
}
~TransactionHelper()
{
Dispose(false);
}
public void
Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void
Dispose(bool disposing)
{
if (disposing) {
if (Trans != null) {
Trans.Dispose();
}
}
}
public virtual void
Start()
{
Trans = Db.TransactionManager.StartTransaction();
}
public virtual void
Commit()
{
Trans.Commit();
Trans = null;
}
public virtual void
Abort()
{
Trans.Abort();
Trans = null;
}
/// <summary>
/// return the underlying Transaction
/// </summary>
public Autodesk.AutoCAD.DatabaseServices.Transaction Transaction
{
get { return Trans; }
}
/// <summary>
/// return the Database that this TransactionHelper goes with
/// </summary>
public Autodesk.AutoCAD.DatabaseServices.Database Database
{
get { return Db; }
}
/// <summary>
/// Wrapper for GetObject method;
/// </summary>
/// <param name="id">Id for object to get.</param>
/// <param name="mode">OpenMode for the object.</param>
/// <returns>The object.</returns>
public DBObject GetObject(ObjectId id, OpenMode mode)
{
return Transaction.GetObject(id, mode);
}
/// <summary>
/// See if a SymbolTableRecord of the given name already exists
/// </summary>
/// <param name="classType">Type of the SymbolTableRecord (e.g., LayerTableRecord)</param>
/// <param name="name">Name of the symbol</param>
/// <returns>True if the symbol already exists, False if it doesn't</returns>
public bool SymbolTableRecExists(System.Type classType, string name)
{
ObjectId tblId = Utils.SymTbl.GetSymbolTableId(classType, Db);
SymbolTable tbl = (SymbolTable)Trans.GetObject(tblId, OpenMode.ForRead);
return tbl.Has(name);
}
/// <summary>
/// Add a new SymbolTableRecord to the database (and the current transaction)
/// </summary>
/// <param name="newRec">A newly allocated SymbolTableRecord which hasn't yet been added to the database</param>
public virtual void AddNewSymbolRec(SymbolTableRecord newRec)
{
ObjectId tblId = Utils.SymTbl.GetSymbolTableId(newRec.GetType(), Db);
SymbolTable tbl = (SymbolTable)Trans.GetObject(tblId, OpenMode.ForWrite);
Debug.Assert(tbl.Has(newRec.Name) == false);
tbl.Add(newRec);
Trans.AddNewlyCreatedDBObject(newRec, true);
}
/// <summary>
/// Define a new named block and add it to the BlockTable. If the block
/// definition already exists, its contents will be emptied out so that
/// the block can be re-defined.
/// </summary>
/// <param name="blkName">Name of the BlockDef</param>
/// <param name="blkRec">New or existing BlockTableRecord</param>
/// <param name="db">Specific database we are using</param>
public BlockTableRecord DefineNewBlockRec(string blkName)
{
BlockTableRecord blkRec = null;
BlockTable tbl = (BlockTable)Trans.GetObject(Db.BlockTableId, OpenMode.ForWrite);
// if it already exists, we are re-defining it and we need to
// erase all the existing entities
if (tbl.Has(blkName)) {
blkRec = (BlockTableRecord)Trans.GetObject(tbl[blkName], OpenMode.ForWrite);
// erase all
DBObject tmpObj = null;
foreach (ObjectId objId in blkRec) {
tmpObj = Trans.GetObject(objId, OpenMode.ForWrite);
if (tmpObj != null) {
tmpObj.Erase(true);
}
}
}
else {
blkRec = new BlockTableRecord();
blkRec.Name = blkName;
tbl.Add(blkRec);
Trans.AddNewlyCreatedDBObject(blkRec, true);
}
return blkRec;
}
/// <summary>
/// Check if database has a block defined by inputed name.
/// </summary>
/// <param name="blkName">Block name to check for.</param>
/// <returns>True if block excist, else false.</returns>
public bool Has(string blkName)
{
BlockTable tbl = (BlockTable)Trans.GetObject(Db.BlockTableId, OpenMode.ForRead);
if (tbl.Has(blkName))
return true;
else
return false;
}
/// <summary>
/// Define a new Anonymous block and add it to the BlockTable
/// </summary>
/// <param name="db"></param>
/// <returns>an open BlockTableRecord, ready to add Entities to</returns>
public BlockTableRecord DefineNewAnonymousBlockRec()
{
BlockTableRecord blkRec = null;
BlockTable tbl = (BlockTable)Trans.GetObject(Db.BlockTableId, OpenMode.ForWrite);
blkRec = new BlockTableRecord();
blkRec.Name = "*U";
tbl.Add(blkRec);
Trans.AddNewlyCreatedDBObject(blkRec, true);
return blkRec;
}
/// <summary>
/// Given the ObjectId of a SymbolTableRecord, get its name
/// </summary>
/// <param name="symId">ObjectId of the SymbolTableRecord</param>
/// <returns>name of the SymbolTableRecord</returns>
public string SymbolIdToName(ObjectId symId)
{
string str = null;
DBObject tmpObj = Trans.GetObject(symId, OpenMode.ForRead);
SymbolTableRecord rec = tmpObj as SymbolTableRecord;
if (rec != null)
str = rec.Name;
return str;
}
public bool IsOnLockedLayer(Entity ent, bool printMsg)
{
Debug.Assert(Trans != null);
LayerTableRecord layer = (LayerTableRecord)Trans.GetObject(ent.LayerId, OpenMode.ForRead);
if (printMsg && layer.IsLocked) {
Utils.AcadUi.PrintToCmdLine("\nSelected entity is on a locked layer.");
}
return layer.IsLocked;
}
public ObjectIdCollection CollectBlockIds(bool excludeMsPs, bool excludeXref, bool excludeXrefDep, bool excludeAnonymous)
{
BlockTable blkTbl = (BlockTable)Trans.GetObject(Db.BlockTableId, OpenMode.ForRead);
// iterate over each BlockTableRecord in the BlockTable
ObjectIdCollection blkRecIds = new ObjectIdCollection();
foreach (ObjectId tblRecId in blkTbl) {
BlockTableRecord blkRec = (BlockTableRecord)Trans.GetObject(tblRecId, OpenMode.ForRead);
if (excludeMsPs && blkRec.IsLayout) {
; // do nothing
}
else if ((excludeXrefDep) && blkRec.IsDependent) {
; // do nothing
}
else if ((excludeXref) &&
((blkRec.IsFromExternalReference) ||
(blkRec.IsFromOverlayReference))) {
; // do nothing
}
else if (excludeAnonymous && blkRec.IsAnonymous) {
; // do nothing
}
else {
blkRecIds.Add(tblRecId);
}
}
return blkRecIds;
}
}//class
}//namespace