Accessing a Block in the background, editing an attribute, and then saving that change
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I have worked on a project where a windows form opens, and a user can select blocks that are logged in a SQL database, make some edits on the blocks, and then post those changes. These blocks are spread across multiple drawings.
I seem to have been successful at opening a drawing in the background via its database, finding the correct Block via its handle, access al attributes and even change the attribute.textstring to my test string ("HELLO WORLD"). When I commit the changes, I don't receive an exception, but when I opened the drawing file in AutoCAD, the change has not been made. This has me conclude that I have to save the drawing after I make the change. So, then I add the db.SaveAs line at the end, but this is causing issues.
I think I am running into an issue at his line: db.SaveAs(FilePath,DwgVersion.Current);
I get FilerError.
How can I save the db to cement my changes to the attributes to the block.
public static Database OpenDrawingFile(string filePath)
{
Document doc = null;
Database database = new Database();
try
{
DocumentCollection acDocs = Application.DocumentManager;
// Check if the document is already open
foreach (Document d in acDocs)
{
if (d.Name.Equals(filePath, StringComparison.OrdinalIgnoreCase))
{
database = d.Database;
break;
}
}
// Open the document if not already open
if (doc == null)
{
Debug.Print($"Opened:{filePath}");
database.ReadDwgFile(filePath, FileOpenMode.OpenForReadAndWriteNoShare, true, null);
}
}
catch (System.Exception ex)
{
// Handle exceptions
Console.WriteLine(ex.Message);
}
return database;
}
public static ObjectId GetBlockIdByHandle(Database db, string blockHandle)
{
ObjectId blockId = ObjectId.Null;
try
{
Transaction tr = db.TransactionManager.StartTransaction();
// Open the block table
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// Open the block table record for the model space
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
// Iterate through the entities in the model space
foreach (ObjectId objId in btr)
{
if (objId.ObjectClass.DxfName == "INSERT")
{
BlockReference blockRef = tr.GetObject(objId, OpenMode.ForRead) as BlockReference;
// Check if the block reference has the specified handle
if (blockRef != null && blockRef.Handle.ToString() == blockHandle)
{
Debug.Print($"Handle Found:{blockRef.Handle}");
blockId = blockRef.ObjectId;
break;
}
}
}
tr.Commit();
}
catch (System.Exception ex)
{
// Handle exceptions
Console.WriteLine(ex.Message);
}
return blockId;
}
public static void ModifyBlock(Database db, ObjectId blockId, DB_Delta Delta, string FilePath)
{
try
{
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
DBObject obj = tr.GetObject(blockId, OpenMode.ForWrite);
if (obj is BlockReference blockRef)
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead);
Debug.Print($"{btr.Name}");
foreach (ObjectId attId in blockRef.AttributeCollection)
{
AttributeReference attRef = (AttributeReference)attId.GetObject(OpenMode.ForWrite);
Debug.Print($"{attRef.Tag}:{attRef.TextString}");
if(attRef.Tag == "REASON")
{
Debug.Print($"Changing {attRef.TextString} to \"HELLO WORLD\"");
attRef.TextString = "HELLO WORLD";
}
}
}
tr.Commit();
}
db.SaveAs(FilePath,DwgVersion.Current);
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
Console.WriteLine(ex.Message);
}
catch (System.Exception ex)
{
// Handle exceptions
Console.WriteLine(ex.Message);
}
}