I need to read a lot of entities from attached drawings, but their database seems empty.
Is there a way to get ids from a database of an attached drawing? Below I show in code exactly what I mean:
I am searching for a solution to "Teste2" below because I already have a lot of code dependent on a "ProjectModel" (specifically, I need to get the entities that have a certain OD Table and get their positions and other features). The code works when the drawing is open, but I need the code to work as side/attached drawing.
So, as side drawing, we can get the ids from entities inside model space:
[CommandMethod(PublicConsts.TituloProgAutomacao, "Teste1", CommandFlags.Modal)]
public void Teste1()
{
string fileName = @"Omitted_for_safety.DWG";
//create side drawing
Database db = new Database(false, true);
db.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, false, "");
//create transaction and get model space
Transaction trans = db.TransactionManager.StartTransaction();
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
ObjectId spaceId = bt[BlockTableRecord.ModelSpace];
BlockTableRecord spaceBlock = (BlockTableRecord)trans.GetObject(spaceId, OpenMode.ForRead);
//this returns a full list of ids inside model space
List<ObjectId> dbIds = spaceBlock.OfType<ObjectId>().ToList();
}
But, as an attached drawing, we are unable to do that:
[CommandMethod(PublicConsts.TituloProgAutomacao, "Teste2", CommandFlags.Modal)]
public void Teste2()
{
string fileAlias = "Omitted_For_Safety.dwg";
//Attach the target drawing and get its database
ProjectModel activeDocument = HostMapApplicationServices.Application.ActiveProject;
AttachedDrawing attached = activeDocument.DrawingSet.AttachDrawing(fileAlias);
Database db = attached.Project.Database;
//create transaction and get model space
Transaction trans = db.TransactionManager.StartTransaction();
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
ObjectId spaceId = bt[BlockTableRecord.ModelSpace];
BlockTableRecord spaceBlock = (BlockTableRecord)trans.GetObject(spaceId, OpenMode.ForRead);
//this returns ZERO ids
List<ObjectId> dbIds = spaceBlock.OfType<ObjectId>().ToList();
}
Solved! Go to Solution.
I need to read a lot of entities from attached drawings, but their database seems empty.
Is there a way to get ids from a database of an attached drawing? Below I show in code exactly what I mean:
I am searching for a solution to "Teste2" below because I already have a lot of code dependent on a "ProjectModel" (specifically, I need to get the entities that have a certain OD Table and get their positions and other features). The code works when the drawing is open, but I need the code to work as side/attached drawing.
So, as side drawing, we can get the ids from entities inside model space:
[CommandMethod(PublicConsts.TituloProgAutomacao, "Teste1", CommandFlags.Modal)]
public void Teste1()
{
string fileName = @"Omitted_for_safety.DWG";
//create side drawing
Database db = new Database(false, true);
db.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, false, "");
//create transaction and get model space
Transaction trans = db.TransactionManager.StartTransaction();
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
ObjectId spaceId = bt[BlockTableRecord.ModelSpace];
BlockTableRecord spaceBlock = (BlockTableRecord)trans.GetObject(spaceId, OpenMode.ForRead);
//this returns a full list of ids inside model space
List<ObjectId> dbIds = spaceBlock.OfType<ObjectId>().ToList();
}
But, as an attached drawing, we are unable to do that:
[CommandMethod(PublicConsts.TituloProgAutomacao, "Teste2", CommandFlags.Modal)]
public void Teste2()
{
string fileAlias = "Omitted_For_Safety.dwg";
//Attach the target drawing and get its database
ProjectModel activeDocument = HostMapApplicationServices.Application.ActiveProject;
AttachedDrawing attached = activeDocument.DrawingSet.AttachDrawing(fileAlias);
Database db = attached.Project.Database;
//create transaction and get model space
Transaction trans = db.TransactionManager.StartTransaction();
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
ObjectId spaceId = bt[BlockTableRecord.ModelSpace];
BlockTableRecord spaceBlock = (BlockTableRecord)trans.GetObject(spaceId, OpenMode.ForRead);
//this returns ZERO ids
List<ObjectId> dbIds = spaceBlock.OfType<ObjectId>().ToList();
}
Solved! Go to Solution.
Solved by danielmollerX5W2N. Go to Solution.
Since you want to grab entities in attached drawing, you do not use ProjectModel.Database as your code does (attached.Project.Database), you should use AttachedDrawing.Database. That is, that line of code in your "Test2" command should simply be:
AttachedDrawing attached = activeDocument.DrawingSet....
var db = attached.Database; // Then do whatever with the database of the attached drawing
... ...
HTH
Norman Yuan
Since you want to grab entities in attached drawing, you do not use ProjectModel.Database as your code does (attached.Project.Database), you should use AttachedDrawing.Database. That is, that line of code in your "Test2" command should simply be:
AttachedDrawing attached = activeDocument.DrawingSet....
var db = attached.Database; // Then do whatever with the database of the attached drawing
... ...
HTH
Norman Yuan
Thank you, Norman.
That leads me to another question: how do I get the OD Table records for the attached drawing?
Thank you, Norman.
That leads me to another question: how do I get the OD Table records for the attached drawing?
While you need to access entities in the attached drawing's Database, the OD tables in the attached drawing are accessible in the ActiveProject.ODTables[tableName].
Norman Yuan
While you need to access entities in the attached drawing's Database, the OD tables in the attached drawing are accessible in the ActiveProject.ODTables[tableName].
Norman Yuan
Hello again.
So, I have tried to get `attachedDrawing.Database`, and I keep getting the following:
System.InvalidOperationException: Operation is not valid due to the current state of the object.
I have tried both with and without `CommandFlags.Session` (always using `Modal`, though).
Basically I did:
ProjectModel MainMapDocument = ... get active project
AttachedDrawing attach = MainMapDocument.DrawingSet.AttachDrawing(docPath);
attach.Activate(); //irrelevant for this case, just trying
attach.UnlockForRead(); // irrelevant for this case, just trying
Database docDb = attach.Database; //"state of the object" error here
Hello again.
So, I have tried to get `attachedDrawing.Database`, and I keep getting the following:
System.InvalidOperationException: Operation is not valid due to the current state of the object.
I have tried both with and without `CommandFlags.Session` (always using `Modal`, though).
Basically I did:
ProjectModel MainMapDocument = ... get active project
AttachedDrawing attach = MainMapDocument.DrawingSet.AttachDrawing(docPath);
attach.Activate(); //irrelevant for this case, just trying
attach.UnlockForRead(); // irrelevant for this case, just trying
Database docDb = attach.Database; //"state of the object" error here
With help from Norman Yuan, I finally figured out how to do it.
Thank you, Norman!
So:
So, in short, the solution is like this:
//get the active or main project
ProjectModel MainMapDocument = HostMapApplicationServices.Application.ActiveProject;
//target od table
string odTableName = "TableName";
foreach (string docName in docNames)
{
//attach drawing and lock it
AttachedDrawing attachedDrawing = MainMapDocument.DrawingSet.AttachDrawing(docName);
attachedDrawing.LockForRead(); //necessary to get the database (you might need 'ForWrite')
//get database, start transaction, do stuff
Database db = attachedDrawing.Database;
Transaction trans = db.TransactionManager.StartTransaction();
//
//get desired ids and do whatever needed in the DB
//
//Get od table from the main project
OD.Tables tables = MainMapDocument.ODTables;
if (!tables.IsTableDefined(odTableName))
continue;
OD.Table table = tables[odTableName];
//
//get table records, do what is needed
//
//finish transaction
trans.Commit();
trans.Dispose();
//release the attached drawing
attachedDrawing.UnlockForRead(); //you might need for write
attachedDrawing.Deactivate(); //important - deletes the 'dwk' file
MainMapDocument.DrawingSet.DetachDrawing(attachedDrawing.ObjectId);
}
With help from Norman Yuan, I finally figured out how to do it.
Thank you, Norman!
So:
So, in short, the solution is like this:
//get the active or main project
ProjectModel MainMapDocument = HostMapApplicationServices.Application.ActiveProject;
//target od table
string odTableName = "TableName";
foreach (string docName in docNames)
{
//attach drawing and lock it
AttachedDrawing attachedDrawing = MainMapDocument.DrawingSet.AttachDrawing(docName);
attachedDrawing.LockForRead(); //necessary to get the database (you might need 'ForWrite')
//get database, start transaction, do stuff
Database db = attachedDrawing.Database;
Transaction trans = db.TransactionManager.StartTransaction();
//
//get desired ids and do whatever needed in the DB
//
//Get od table from the main project
OD.Tables tables = MainMapDocument.ODTables;
if (!tables.IsTableDefined(odTableName))
continue;
OD.Table table = tables[odTableName];
//
//get table records, do what is needed
//
//finish transaction
trans.Commit();
trans.Dispose();
//release the attached drawing
attachedDrawing.UnlockForRead(); //you might need for write
attachedDrawing.Deactivate(); //important - deletes the 'dwk' file
MainMapDocument.DrawingSet.DetachDrawing(attachedDrawing.ObjectId);
}
Hello Norman,
Do you have examples, or can you point me to the right place where I can see good examples/explanations of the use of "ActiveProject.ODTables[tableName]."
I am trying to complete a program where it strips everything nonessential from a DWG and save it as a DXF to send to clients. The last successful event my program completes is to export the final product as a DXF. I want to create a method in C# to open the DXF from the end of my program (written in LISP) and remove the MAP OBData. I have a simple LISP routine three lines long that does this nicely but it has to be started with the DXF and I don't want to run it the master DWG.
I have tried ReadDWGFile() and DXFin() and have not had any success. After doing a lot of reading and finally coming across these Help pages I have figured out that "db.DxfIn(dxfFilename, logFilename)" can only attach to the standard/normal DWG database. I now know I need to access the specialized Map Tables.
I am hoping you could help with an example of "ActiveProject.ODTables[tableName]" being used correctly.
The following code is when I decided to start simple and just list the OBTables in another drawing:
public static void ListObjectDataTables()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
// Define the DXF file path
string dxfFilename = @"C:\temp\AG FACILITIES.dxf";
string logFilename = @"C:\temp\dxfin.log";
// Create a new database
Database db = new Database(false, true);
try
{
// Load the DXF file into the database
db.DxfIn(dxfFilename, logFilename);
ed.WriteMessage("\nDXF file loaded successfully.\n");
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// Open the blocktable, get the modelspace
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
// Switch to the DXF database context
using (DocumentLock docLock = doc.LockDocument())
{
HostApplicationServices.WorkingDatabase = db;
// Get the object data tables
Tables odTables = HostMapApplicationServices.Application.ActiveProject.ODTables;
StringCollection allDbTables = odTables.GetTableNames();
ed.WriteMessage("Object Data Tables Names in the DXF file:\n");
// Print out the names of the object data tables
foreach (string tableName in allDbTables)
{
ed.WriteMessage(tableName + "\n");
}
}
tr.Commit();
}
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
ed.WriteMessage($"\nAutoCAD error: {ex.Message}\n");
}
catch (System.Exception ex)
{
ed.WriteMessage($"\nError: {ex.Message}\n");
}
finally
{
db.Dispose();
}
}
It runs nicely, if you don't want it to do anything.
Thank you.
Hello Norman,
Do you have examples, or can you point me to the right place where I can see good examples/explanations of the use of "ActiveProject.ODTables[tableName]."
I am trying to complete a program where it strips everything nonessential from a DWG and save it as a DXF to send to clients. The last successful event my program completes is to export the final product as a DXF. I want to create a method in C# to open the DXF from the end of my program (written in LISP) and remove the MAP OBData. I have a simple LISP routine three lines long that does this nicely but it has to be started with the DXF and I don't want to run it the master DWG.
I have tried ReadDWGFile() and DXFin() and have not had any success. After doing a lot of reading and finally coming across these Help pages I have figured out that "db.DxfIn(dxfFilename, logFilename)" can only attach to the standard/normal DWG database. I now know I need to access the specialized Map Tables.
I am hoping you could help with an example of "ActiveProject.ODTables[tableName]" being used correctly.
The following code is when I decided to start simple and just list the OBTables in another drawing:
public static void ListObjectDataTables()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
// Define the DXF file path
string dxfFilename = @"C:\temp\AG FACILITIES.dxf";
string logFilename = @"C:\temp\dxfin.log";
// Create a new database
Database db = new Database(false, true);
try
{
// Load the DXF file into the database
db.DxfIn(dxfFilename, logFilename);
ed.WriteMessage("\nDXF file loaded successfully.\n");
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// Open the blocktable, get the modelspace
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
// Switch to the DXF database context
using (DocumentLock docLock = doc.LockDocument())
{
HostApplicationServices.WorkingDatabase = db;
// Get the object data tables
Tables odTables = HostMapApplicationServices.Application.ActiveProject.ODTables;
StringCollection allDbTables = odTables.GetTableNames();
ed.WriteMessage("Object Data Tables Names in the DXF file:\n");
// Print out the names of the object data tables
foreach (string tableName in allDbTables)
{
ed.WriteMessage(tableName + "\n");
}
}
tr.Commit();
}
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
ed.WriteMessage($"\nAutoCAD error: {ex.Message}\n");
}
catch (System.Exception ex)
{
ed.WriteMessage($"\nError: {ex.Message}\n");
}
finally
{
db.Dispose();
}
}
It runs nicely, if you don't want it to do anything.
Thank you.
You cannot have access to Object Data table (ODTable) from a side-loaded database. You must open the drawing (be it a *.dwg file, or *.dxf file) in AutoCAD editor (with AutoCAD Map or C3D, of course), or, you open the DWG/DXF file as AutoCAD Map project's AttachedDrawing.
From your description, you have a DXF file, you want to remove (or have access to, for that matters) the ODTables in the DXF file. So, you simply open it in AutoCAD Map/C3D, Then you can reach ODTables by
Tables odTables = HostMapApplicationServices.Application.ActiveProject.ODTables;
Norman Yuan
You cannot have access to Object Data table (ODTable) from a side-loaded database. You must open the drawing (be it a *.dwg file, or *.dxf file) in AutoCAD editor (with AutoCAD Map or C3D, of course), or, you open the DWG/DXF file as AutoCAD Map project's AttachedDrawing.
From your description, you have a DXF file, you want to remove (or have access to, for that matters) the ODTables in the DXF file. So, you simply open it in AutoCAD Map/C3D, Then you can reach ODTables by
Tables odTables = HostMapApplicationServices.Application.ActiveProject.ODTables;
Norman Yuan
Wow, thanks for the quick response!
There is my problem, I do not want to open the DXF with Map and then remove the OB Data. I am trying to automate this work for others. From their master working DWG, they preform my DXFout function (a little more involved than the standard DXFOUT command) and the last thing that should happen is the removal of the OB Data on the external DXF file. I want to attach it as a Project - I think that is what I read, similar in concepts as ReadDWGFile/DXFin. The Autodesk Map community is much smaller than the standard CAD group that it is hard for me at least to find good resources and examples.
Wow, thanks for the quick response!
There is my problem, I do not want to open the DXF with Map and then remove the OB Data. I am trying to automate this work for others. From their master working DWG, they preform my DXFout function (a little more involved than the standard DXFOUT command) and the last thing that should happen is the removal of the OB Data on the external DXF file. I want to attach it as a Project - I think that is what I read, similar in concepts as ReadDWGFile/DXFin. The Autodesk Map community is much smaller than the standard CAD group that it is hard for me at least to find good resources and examples.
I do not know the details on how do you exactly run the process. But you have to run AutoCAD MAP/C3D session with your .NET API code, right?
So, if you really do not want to VISIBLY open the DWG/DFX file, then you would have a drawing opened (be it blank/empty one, or any existing drawing) as the Map's ProjectModel, then you need to write code to create Aliases for attach the DWG/DXF file as AttachedDrawing. Only after these 2 steps done, then you can have access to the ODTables in the current drawing and in the attached drawing. The attached drawing is similar to side-opened database, but for accessing MAP objects, you must either directly open the file in AutoCAD MAP/C3D, or open them as attached drawings. The code showed by @danielmollerX5W2N did not include how to programmatically create Aliases for attaching drawings. So, in comparison to simply open the drawing, the code is more complicated.
If you need to do a batch of DXF process for this purpose, you may consider to use core console to open the file and strip the OD data from each file. It is quite fast, in comparison to open drawing in desktop AutoCAD session.
Norman Yuan
I do not know the details on how do you exactly run the process. But you have to run AutoCAD MAP/C3D session with your .NET API code, right?
So, if you really do not want to VISIBLY open the DWG/DFX file, then you would have a drawing opened (be it blank/empty one, or any existing drawing) as the Map's ProjectModel, then you need to write code to create Aliases for attach the DWG/DXF file as AttachedDrawing. Only after these 2 steps done, then you can have access to the ODTables in the current drawing and in the attached drawing. The attached drawing is similar to side-opened database, but for accessing MAP objects, you must either directly open the file in AutoCAD MAP/C3D, or open them as attached drawings. The code showed by @danielmollerX5W2N did not include how to programmatically create Aliases for attaching drawings. So, in comparison to simply open the drawing, the code is more complicated.
If you need to do a batch of DXF process for this purpose, you may consider to use core console to open the file and strip the OD data from each file. It is quite fast, in comparison to open drawing in desktop AutoCAD session.
Norman Yuan
Thank you again for the quick response and sorry for my delayed reply.
I will look into these processes, attaching the DXF as a project model then creating an alias.
Also, Accoreconsole.exe was my first attempt and that didn't work. There is an issue with my accoreconsole not staying open to run code and my IT have been sitting on this for over a month. So I could never test if a script file worked or not.
Thanks again.
Thank you again for the quick response and sorry for my delayed reply.
I will look into these processes, attaching the DXF as a project model then creating an alias.
Also, Accoreconsole.exe was my first attempt and that didn't work. There is an issue with my accoreconsole not staying open to run code and my IT have been sitting on this for over a month. So I could never test if a script file worked or not.
Thanks again.
Can't find what you're looking for? Ask the community or share your knowledge.