using System;
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.EditorInput;
.................................................
public static ObjectId CreateLabelBlock(string blockname)
{
ObjectId blkid = ObjectId.Null;
try
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite, false);
if (bt.Has(blockname))
{
blkid = bt[blockname];
}
else
{
BlockTableRecord btr = new BlockTableRecord();
btr.Name = blockname;
btr.Explodable = true;
btr.Origin = new Point3d(0, 0, 0);
btr.Units = UnitsValue.Inches;
btr.BlockScaling = BlockScaling.Any;
Line line = new Line(new Point3d(-2, -0.4, 0), new Point3d(2, -0.4, 0));
line.Layer = "0";
line.ColorIndex = 14;
btr.AppendEntity(line);
line = new Line(new Point3d(-2, 0.4, 0), new Point3d(2, 0.4, 0));
line.Layer = "0";
line.ColorIndex = 14;
btr.AppendEntity(line);
line = new Line(new Point3d(2, -0.4, 0), new Point3d(2, 0.4, 0));
line.Layer = "0";
line.ColorIndex = 14;
btr.AppendEntity(line);
line = new Line(new Point3d(-2, -0.4, 0), new Point3d(-2, 0.4, 0));
line.Layer = "0";
line.ColorIndex = 14;
btr.AppendEntity(line);
AcadApp.SetSystemVariable("CECOLOR", "ByBlock");
AttributeDefinition ad = new AttributeDefinition();
ad.Layer = "0";
//by default applied a current text style
ad.Tag = "DETAIL";
ad.TextString = "X-Ladder";
ad.Prompt = "Detail name";
ad.Position = new Point3d(0, 0, 0);
ad.HorizontalMode = TextHorizontalMode.TextMid;
ad.VerticalMode = TextVerticalMode.TextVerticalMid;
ad.AlignmentPoint = ad.Position;
btr.AppendEntity(ad);
blkid = bt.Add(btr);
AcadApp.SetSystemVariable("CECOLOR", "ByLayer");
tr.AddNewlyCreatedDBObject(btr, true);
}
tr.Commit();
}
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
AcadApp.ShowAlertDialog("ERROR: " + "\n" + ex.Message + "\nSOURCE: " + ex.StackTrace);
}
return blkid;
}
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
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;
}
public static ObjectId GetNonErasedTableRecordId( ObjectId TableId, string Name )
// Posted by Tony Tanzillo 01Sept2006
{
ObjectId id = ObjectId.Null;
using( Transaction tr = TableId.Database.TransactionManager.StartTransaction() )
{
SymbolTable table = (SymbolTable) tr.GetObject( TableId, OpenMode.ForRead );
if( table.Has( Name ) )
{
id = table[Name];
if( !id.IsErased )
return id;
foreach( ObjectId recId in table )
{
if( ! recId.IsErased )
{
SymbolTableRecord rec = (SymbolTableRecord) tr.GetObject( recId, OpenMode.ForRead );
if( string.Compare( rec.Name, Name, true ) == 0 )
return recId;
}
}
}
}
return id;
}
' This procedure will insert a block into the current drawing. It also controls the defined attributes and it will
' add the current Annotation Scale if the block is Annotative.
' Code contribution:
' - fro2001 - via TheSwamp.org
Public Sub hzInsertBlockMSWithAttributes(ByVal pntInsert As Geometry.Point3d,
ByVal strBlockName As String,
ByVal dScale As Double,
ByVal strLayerName As String,
ByVal arrAttrValues As ArrayList)
Dim db As Database = HostApplicationServices.WorkingDatabase
Using tr As Transaction = db.TransactionManager.StartTransaction
Dim bt As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead)
Dim btrMS As BlockTableRecord = bt(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForRead)
If Not bt.Has(strBlockName) Then
Exit Sub
Else
btrMS.UpgradeOpen()
End If
Dim btr As BlockTableRecord = bt(strBlockName).GetObject(OpenMode.ForRead)
Dim bref As New BlockReference(pntInsert, btr.ObjectId)
btrMS.AppendEntity(bref)
tr.AddNewlyCreatedDBObject(bref, True)
' set annotation scale if block is annotative
If btr.Annotative = AnnotativeStates.True Then
Dim ocm As ObjectContextManager = db.ObjectContextManager
Dim occ As ObjectContextCollection = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES")
Internal.ObjectContexts.AddContext(bref, occ.CurrentContext)
End If
' set attributes and values
' TODO: Set attribute to layer of block or layer of original definition, now it will be placed on layer 0
' TODO: Check if attribute is annotative, it is possible to create non-annotative blocks with annotative attributes
Dim ccAttCounter As Integer = 0
For Each objId As ObjectId In btr
Dim ent As Entity = objId.GetObject(OpenMode.ForRead)
If TypeOf ent Is AttributeDefinition Then
ent.UpgradeOpen()
Dim attDef As AttributeDefinition = CType(ent, AttributeDefinition)
Dim attRef As New AttributeReference
attRef.SetAttributeFromBlock(attDef, bref.BlockTransform)
' check if there is a value to add
If arrAttrValues.Count - 1 >= ccAttCounter Then
attRef.TextString = arrAttrValues(ccAttCounter).ToString.Trim
Else
attRef.TextString = ""
End If
bref.AttributeCollection.AppendAttribute(attRef)
tr.AddNewlyCreatedDBObject(attRef, True)
ccAttCounter += 1
End If
Next
' set layer
' TODO: Check if layername exist
bref.Layer = strLayerName
' commit
tr.Commit()
End Using
End Sub
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
namespace DuplicateTest
{
public static class BlockRefExtension
{
public static bool Duplicate(this BlockReference blk1, BlockReference blk2)
{
Tolerance tol = new Tolerance(1e-6, 1e-6);
return
blk1.OwnerId == blk2.OwnerId &&
blk1.Name == blk2.Name &&
blk1.Layer == blk2.Layer &&
Math.Round(blk1.Rotation, 5) == Math.Round(blk2.Rotation, 5) &&
blk1.Position.IsEqualTo(blk2.Position, tol) &&
blk1.ScaleFactors.IsEqualTo(blk2.ScaleFactors, tol);
}
}
public class Commands
{
[CommandMethod("Test")]
public void DelDupBlkRef()
{
try
{
int del = DeleteDuplicatedBlockRef();
Application.ShowAlertDialog(del.ToString() + " duplicated block(s) have been erased");
}
catch (System.Exception e)
{
Application.ShowAlertDialog("\nError: " + e.Message);
}
}
private int DeleteDuplicatedBlockRef()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
int result = 0;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
foreach (ObjectId id in bt)
{
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(id, OpenMode.ForWrite);
ObjectIdCollection idCol = btr.GetBlockReferenceIds(true, false);
for (int i = 0; i < idCol.Count; i++)
{
BlockReference blkRef =
(BlockReference)tr.GetObject(idCol[i], OpenMode.ForRead);
for (int j = i + 1; j < idCol.Count; j++)
{
BlockReference br =
(BlockReference)tr.GetObject(idCol[j], OpenMode.ForRead);
if (br.Duplicate(blkRef))
{
idCol.RemoveAt(j);
br.UpgradeOpen();
br.Erase();
j--;
result++;
}
}
}
}
tr.Commit();
}
return result;
}
}
}
module DupBlks
open System
open System.Collections.Generic
open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime
let Duplicate (a: BlockReference) (b: BlockReference) =
let tol = new Tolerance(1e-6, 1e-6)
a.Name = b.Name &&
a.OwnerId = b.OwnerId &&
a.Position = b.Position &&
a.Layer = b.Layer &&
Math.Round(a.Rotation, 6) = Math.Round(b.Rotation, 6) &&
a.ScaleFactors = b.ScaleFactors
let DeleteDuplicatedBlockRef() =
let db = HostApplicationServices.WorkingDatabase
use tr = db.TransactionManager.StartTransaction()
let getRefs (bt: BlockTable) =
let mutable lst = []
for id in bt do
let btr = tr.GetObject(id, OpenMode.ForRead) :?> BlockTableRecord
for oId in btr.GetBlockReferenceIds(true, false) do
lst <- tr.GetObject(oId, OpenMode.ForWrite) :?> BlockReference :: lst
lst
let rec findDups acc blks =
match blks with
| [] -> acc
| h :: t -> let pair = List.partition (fun x -> Duplicate x h) t
findDups (acc @ (fst pair)) (snd pair)
let delBlk lst =
List.iter (fun (x: BlockReference) -> x.Erase()) lst
lst.Length
let cnt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
|> getRefs |> findDups [] |> delBlk
tr.Commit()
cnt
[<CommandMethod("Test")>]
let Test() =
try
let del = DeleteDuplicatedBlockRef()
Application.ShowAlertDialog(del.ToString() + " duplicated block(s) have been erased")
with
|ex -> Application.ShowAlertDialog(ex.Message)
[CommandMethod("DynamicBlocksThingy")]
public void DynamicBlocksThingy()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
using (Transaction trx = db.TransactionManager.StartTransaction())
{
BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
foreach (ObjectId objId in bt)
{
BlockTableRecord btr = (BlockTableRecord)objId.GetObject(OpenMode.ForRead);
if (btr.IsDynamicBlock)
{
ObjectIdCollection brefObjidColl = btr.GetBlockReferenceIds(true, true);
ObjectIdCollection anonObjIdsColl = btr.GetAnonymousBlockIds();
foreach (ObjectId anonObjId in anonObjIdsColl)
{
BlockTableRecord btrAnon = (BlockTableRecord)anonObjId.GetObject(OpenMode.ForRead);
ObjectIdCollection ObjidColl = btrAnon.GetBlockReferenceIds(true, true);
foreach (ObjectId Id in ObjidColl)
brefObjidColl.Add(Id);
}
foreach (ObjectId brefObjId in brefObjidColl)
{
BlockReference bref = brefObjId.GetObject(OpenMode.ForWrite) as BlockReference;
DynamicBlockReferencePropertyCollection dynBrefColl = bref.DynamicBlockReferencePropertyCollection;
foreach (DynamicBlockReferenceProperty dynBrefProps in dynBrefColl)
{
if (dynBrefProps.PropertyName == "Visibility1")
{
dynBrefProps.Value = "Vis2";
}
}
}
}
}
trx.Commit();
}
}
public static ObjectIdCollection GetDynamicBlocksByName(string BlkName)
{
ObjectIdCollection res = new ObjectIdCollection();
Database db = Application.DocumentManager.MdiActiveDocument.Database;
using (Transaction trans = db.TransactionManager.StartTransaction())
{
//get the blockTable and iterate through all block Defs
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
foreach (ObjectId btrId in bt)
{
//get the block Def and see if it is anonymous
BlockTableRecord btr = (BlockTableRecord)trans.GetObject(btrId, OpenMode.ForRead);
if (btr.IsDynamicBlock && btr.Name.Equals(BlkName))
{
//get all anonymous blocks from this dynamic block
ObjectIdCollection anonymousIds = btr.GetAnonymousBlockIds();
ObjectIdCollection dynBlockRefs = new ObjectIdCollection();
foreach (ObjectId anonymousBtrId in anonymousIds)
{
//get the anonymous block
BlockTableRecord anonymousBtr = (BlockTableRecord)trans.GetObject(anonymousBtrId, OpenMode.ForRead);
//and all references to this block
ObjectIdCollection blockRefIds = anonymousBtr.GetBlockReferenceIds(true, true);
foreach (ObjectId id in blockRefIds) dynBlockRefs.Add(id);
}
res = dynBlockRefs;
break;
}
}
trans.Commit();
}
return res;
}
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace AttributeExtraction
{
public class BlockAttribute
{
private string _name;
private Dictionary<string, string> _atts;
// Public read only properties
public string Name
{
get { return _name; }
}
public Dictionary<string, string> Attributes
{
get { return _atts; }
}
public string this[string key]
{
get { return _atts[key.ToUpper()]; }
}
// Constructors
public BlockAttribute(BlockReference br)
{
SetProperties(br);
}
public BlockAttribute(ObjectId id)
{
Document doc = AcAp.DocumentManager.MdiActiveDocument;
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
SetProperties(tr.GetObject(id, OpenMode.ForRead) as BlockReference);
}
}
// Public method
new public string ToString()
{
if (_atts != null && _atts.Count > 0)
return string.Format("{0}: {1}",
_name,
_atts.Select(a => string.Format("{0}={1}", a.Key, a.Value))
.Aggregate((a, b) => string.Format("{0}; {1}", a, b)));
return _name;
}
// Private method
private void SetProperties(BlockReference br)
{
if (br == null) return;
_name = br.GetEffectiveName();
_atts = new Dictionary<string, string>();
br.AttributeCollection
.GetObjects<AttributeReference>()
.Iterate(att => _atts.Add(att.Tag.ToUpper(), att.TextString));
}
}
public class BlockAttributeEqualityComparer : IEqualityComparer<BlockAttribute>
{
public bool Equals(BlockAttribute x, BlockAttribute y)
{
return
x.Name.Equals(y.Name, StringComparison.CurrentCultureIgnoreCase) &&
x.Attributes.SequenceEqual(y.Attributes);
}
public int GetHashCode(BlockAttribute obj)
{
return base.GetHashCode();
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using AcDataTable = Autodesk.AutoCAD.DatabaseServices.DataTable;
namespace AttributeExtraction
{
public static class Extensions
{
// Opens a DBObject in ForRead mode (kaefer @ TheSwamp)
public static T GetObject<T>(this ObjectId id) where T : DBObject
{
return id.GetObject<T>(OpenMode.ForRead);
}
// Opens a DBObject in the given mode (kaefer @ TheSwamp)
public static T GetObject<T>(this ObjectId id, OpenMode mode) where T : DBObject
{
return id.GetObject(mode) as T;
}
// Opens a collection of DBObject in ForRead mode (kaefer @ TheSwamp)
public static IEnumerable<T> GetObjects<T>(this IEnumerable ids) where T : DBObject
{
return ids.GetObjects<T>(OpenMode.ForRead);
}
// Opens a collection of DBObject in the given mode (kaefer @ TheSwamp)
public static IEnumerable<T> GetObjects<T>(this IEnumerable ids, OpenMode mode) where T : DBObject
{
return ids
.Cast<ObjectId>()
.Select(id => id.GetObject<T>(mode))
.Where(res => res != null);
}
// Applies the given Action to each element of the collection (mimics the F# Seq.iter function).
public static void Iterate<T>(this IEnumerable<T> collection, Action<T> action)
{
foreach (T item in collection) action(item);
}
// Applies the given Action to each element of the collection (mimics the F# Seq.iteri function).
// The integer passed to the Action indicates the index of element.
public static void Iterate<T>(this IEnumerable<T> collection, Action<T, int> action)
{
int i = 0;
foreach (T item in collection) action(item, i++);
}
// Gets the block effective name (anonymous dynamic blocs).
public static string GetEffectiveName(this BlockReference br)
{
if (br.IsDynamicBlock)
return br.DynamicBlockTableRecord.GetObject<BlockTableRecord>().Name;
return br.Name;
}
// Creates a System.Data.DataTable from a BlockAttribute collection.
public static System.Data.DataTable ToDataTable(this IEnumerable<BlockAttribute> blockAtts, string name)
{
System.Data.DataTable dTable = new System.Data.DataTable(name);
dTable.Columns.Add("Name", typeof(string));
dTable.Columns.Add("Quantity", typeof(int));
blockAtts
.GroupBy(blk => blk, (blk, blks) => new { Block = blk, Count = blks.Count() }, new BlockAttributeEqualityComparer())
.Iterate(row =>
{
System.Data.DataRow dRow = dTable.Rows.Add(row.Block.Name, row.Count);
row.Block.Attributes.Iterate(att =>
{
if (!dTable.Columns.Contains(att.Key))
dTable.Columns.Add(att.Key);
dRow[att.Key] = att.Value;
});
});
return dTable;
}
// Gets the column names collection of the datatable
public static IEnumerable<string> GetColumnNames(this System.Data.DataTable dataTbl)
{
return dataTbl.Columns.Cast<System.Data.DataColumn>().Select(col => col.ColumnName);
}
// Writes an Excel file from the datatable (using late binding)
public static void WriteXls(this System.Data.DataTable dataTbl, string filename, string sheetName, bool visible)
{
object mis = Type.Missing;
object xlApp = LateBinding.GetOrCreateInstance("Excel.Application");
xlApp.Set("DisplayAlerts", false);
object workbooks = xlApp.Get("Workbooks");
object workbook, worksheet;
if (File.Exists(filename))
workbook = workbooks.Invoke("Open", filename);
else
workbook = workbooks.Invoke("Add", mis);
if (string.IsNullOrEmpty(sheetName))
worksheet = workbook.Get("Activesheet");
else
{
object worksheets = workbook.Get("Worksheets");
try
{
worksheet = worksheets.Get("Item", sheetName);
worksheet.Get("Cells").Invoke("Clear");
}
catch
{
worksheet = worksheets.Invoke("Add", mis);
worksheet.Set("Name", sheetName);
}
}
object range = worksheet.Get("Cells");
dataTbl.GetColumnNames()
.Iterate((name, i) => range.Get("Item", 1, i + 1).Set("Value2", name));
dataTbl.Rows
.Cast<DataRow>()
.Iterate((row, i) => row.ItemArray
.Iterate((item, j) => range.Get("Item", i + 2, j + 1).Set("Value2", item)));
xlApp.Set("DisplayAlerts", true);
if (visible)
{
xlApp.Set("Visible", true);
}
else
{
if (File.Exists(filename))
workbook.Invoke("Save");
else
{
int fileFormat =
string.Compare("11.0", (string)xlApp.Get("Version")) < 0 &&
filename.EndsWith(".xlsx", StringComparison.CurrentCultureIgnoreCase) ?
51 : -4143;
workbook.Invoke("Saveas", filename, fileFormat, string.Empty, string.Empty, false, false, 1, 1);
}
workbook.Invoke("Close");
workbook = null;
xlApp.ReleaseInstance();
xlApp = null;
}
}
// Writes a csv file from the datatable.
public static void WriteCsv(this System.Data.DataTable dataTbl, string filename)
{
using (StreamWriter writer = new StreamWriter(filename))
{
writer.WriteLine(dataTbl.GetColumnNames().Aggregate((s1, s2) => string.Format("{0},{1}", s1, s2)));
dataTbl.Rows
.Cast<DataRow>()
.Select(row => row.ItemArray.Aggregate((s1, s2) => string.Format("{0},{1}", s1, s2)))
.Iterate(line => writer.WriteLine(line));
}
}
// Creates an AutoCAD Table from the datatable.
public static Table ToAcadTable(this System.Data.DataTable dataTbl, double rowHeight, double columnWidth)
{
//return dataTbl.Rows.Cast<DataRow>().ToAcadTable(dataTbl.TableName, dataTbl.GetColumnNames(), rowHeight, columnWidth);
Table tbl = new Table();
tbl.Rows[0].Height = rowHeight;
tbl.Columns[0].Width = columnWidth;
tbl.InsertColumns(0, columnWidth, dataTbl.Columns.Count - 1);
tbl.InsertRows(0, rowHeight, dataTbl.Rows.Count + 1);
tbl.Cells[0, 0].Value = dataTbl.TableName;
dataTbl.GetColumnNames()
.Iterate((name, i) => tbl.Cells[1, i].Value = name);
dataTbl.Rows
.Cast<DataRow>()
.Iterate((row, i) =>
row.ItemArray.Iterate((item, j) =>
tbl.Cells[i + 2, j].Value = item));
return tbl;
}
}
}
using BF = System.Reflection.BindingFlags;
namespace AttributeExtraction
{
public static class LateBinding
{
public static object GetInstance(string appName)
{
return System.Runtime.InteropServices.Marshal.GetActiveObject(appName);
}
public static object CreateInstance(string appName)
{
return System.Activator.CreateInstance(System.Type.GetTypeFromProgID(appName));
}
public static object GetOrCreateInstance(string appName)
{
try { return GetInstance(appName); }
catch { return CreateInstance(appName); }
}
public static object Get(this object obj, string propName, params object[] parameter)
{
return obj.GetType().InvokeMember(propName, BF.GetProperty, null, obj, parameter);
}
public static void Set(this object obj, string propName, params object[] parameter)
{
obj.GetType().InvokeMember(propName, BF.SetProperty, null, obj, parameter);
}
public static object Invoke(this object obj, string methName, params object[] parameter)
{
return obj.GetType().InvokeMember(methName, BF.InvokeMethod, null, obj, parameter);
}
public static void ReleaseInstance(this object obj)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
}
}
}
using System.Linq;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace AttributeExtraction
{
public class Commands
{
[CommandMethod("Test")]
public void Test()
{
Document doc = AcAp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
TypedValue[] filter = { new TypedValue(0, "INSERT") };
PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
if (psr.Status != PromptStatus.OK) return;
PromptPointResult ppr = ed.GetPoint("\nInsertion point: ");
if (ppr.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
System.Data.DataTable dataTable = psr.Value.GetObjectIds()
.Select(id => new BlockAttribute(id.GetObject<BlockReference>()))
.ToDataTable("Extraction");
Table tbl = dataTable.ToAcadTable(9.0, 40.0);
tbl.Position = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);
BlockTableRecord btr = db.CurrentSpaceId.GetObject<BlockTableRecord>(OpenMode.ForWrite);
btr.AppendEntity(tbl);
tr.AddNewlyCreatedDBObject(tbl, true);
try
{
string filename = (string)AcAp.GetSystemVariable("dwgprefix") + "Extraction.xls";
dataTable.WriteXls(filename, null, true);
}
catch
{
AcAp.ShowAlertDialog("Failed to open Excel");
}
tr.Commit();
}
}
}
}
Here's a little example for attributes extraction.
// Original written in C# by gile @ theswamp
// http://www.theswamp.org/index.php?topic=31859.msg452527#msg452527
module AttributeExtraction
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime
open System.Data
type acadApp = Autodesk.AutoCAD.ApplicationServices.Application
// type test returning 'T option
let ofType<'T> : obj -> _ =
box
>> function :? 'T as t -> Some t | _ -> None
// get DBObject for read and cast to 'T, if type parameter present
let getObject<'T when 'T :> DBObject> (oid: ObjectId) =
oid.GetObject OpenMode.ForRead
|> unbox<'T>
// get all objects from an untyped sequence, and try to cast them to 'T
let getObjects<'T when 'T :> DBObject> : System.Collections.IEnumerable -> _ =
Seq.cast<ObjectId>
>> Seq.choose (getObject >> ofType<'T>)
// F# record type to encapsulate a block reference and its attributes
type BlockAttribute =
{
Name : string
Attributes : Map<string,string>
} with
// indexer method
member me.Item (key : string) = me.Attributes.[key.ToUpper()]
override me.ToString() =
if me.Attributes.IsEmpty then
me.Name
else
let sb = new System.Text.StringBuilder()
me.Attributes
|> Map.fold (fun first k v ->
if first then
sb.AppendFormat("{0}: {1}={2}", me.Name, k, v)
else
sb.AppendFormat("; {0}={1}", k, v)
|> ignore
false ) true |> ignore
sb.ToString()
// Ersatz constructors
static member Create oid = BlockAttribute.Create (getObject oid)
static member Create(br : BlockReference) =
{ Name =
// Gets the block effective name (anonymous dynamic blocs)
if br.IsDynamicBlock then
(getObject<BlockTableRecord> br.DynamicBlockTableRecord).Name
else
br.Name
Attributes =
getObjects<AttributeReference> br.AttributeCollection
|> Seq.map (fun ar -> ar.Tag.ToUpper(), ar.TextString)
|> Map.ofSeq }
// Create a Datatable from a BlockAttribute collection
let toDataTable name blockAtts =
let dTable = new System.Data.DataTable(name)
dTable.Columns.Add("Name", typeof<string>) |> ignore
dTable.Columns.Add("Quantity", typeof<int>) |> ignore
blockAtts
|> Seq.groupBy id
|> Seq.map (fun (blk, blks) -> blk, Seq.length blks)
|> Seq.iter (fun (blk, bcnt) ->
let dRow = dTable.Rows.Add(blk.Name, bcnt)
for KeyValue(k, v) in blk.Attributes do
if not(dTable.Columns.Contains k) then
dTable.Columns.Add k |> ignore
dRow.[k] <- v )
dTable
// Create an AutoCAD Table from a Datatable
let toAcadTable rowHeight columnWidth (dTable : System.Data.DataTable) =
let tbl = new Table()
tbl.Rows.[0].Height <- rowHeight
tbl.Columns.[0].Width <- columnWidth
tbl.InsertColumns(0, columnWidth, dTable.Columns.Count - 1)
tbl.InsertRows(0, rowHeight, dTable.Rows.Count + 1)
tbl.Cells.[0, 0].Value <- dTable.TableName
for x in 0 .. dTable.Columns.Count - 1 do
let col = dTable.Columns.[x]
tbl.Cells.[1, x].Value <- col.ColumnName
for y in 0 .. dTable.Rows.Count - 1 do
tbl.Cells.[y + 2, x].Value <- dTable.Rows.[y].[col]
tbl
// Test command
[<CommandMethod("TestF", CommandFlags.UsePickSet)>]
let testCommand() =
let doc = acadApp.DocumentManager.MdiActiveDocument
let db = doc.Database
let ed = doc.Editor
let filter = [| new TypedValue(0, "INSERT") |]
let psr = ed.GetSelection(new SelectionFilter(filter))
if psr.Status = PromptStatus.OK then
let ppr = ed.GetPoint "\nInsertion point: "
if ppr.Status = PromptStatus.OK then
use tr = db.TransactionManager.StartTransaction()
let tbl =
psr.Value.GetObjectIds()
|> Seq.map BlockAttribute.Create
|> toDataTable "Extraction"
|> toAcadTable 9.0 40.0
tbl.Position <- ppr.Value.TransformBy ed.CurrentUserCoordinateSystem
let btr : BlockTableRecord = getObject db.CurrentSpaceId
btr.UpgradeOpen()
btr.AppendEntity tbl |> ignore
tr.AddNewlyCreatedDBObject(tbl, true)
tr.Commit()
- tries to be more imperative "in the small" because for foo in bar do ... reads nicer than bar |> Seq.iter (fun foo -> ...)This is funny, while I try to write C# in a more functional/declarative style, you write F# in a more imperative one.
[CommandMethod("AppendAttributeToBlock","appatt", CommandFlags.Session | CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)]
public static void AppendAttributeTest()
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
try
{
using (doc.LockDocument())
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord currSp = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
PromptNestedEntityOptions pno =
new PromptNestedEntityOptions("\nSelect source attribute to append new attribute below this one >>");
PromptNestedEntityResult nres =
ed.GetNestedEntity(pno);
if (nres.Status != PromptStatus.OK)
return;
ObjectId id = nres.ObjectId;
Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
Point3d pnt = nres.PickedPoint;
ObjectId owId = ent.OwnerId;
AttributeReference attref = null;
if (id.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(AttributeReference))))
{
attref = tr.GetObject(id,OpenMode.ForWrite) as AttributeReference;
}
BlockTableRecord btr = null;
BlockReference bref = null;
if (owId.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(BlockReference))))
{
bref = tr.GetObject(owId,OpenMode.ForWrite) as BlockReference;
if (bref.IsDynamicBlock)
{
btr = tr.GetObject(bref.DynamicBlockTableRecord,OpenMode.ForRead) as BlockTableRecord;
}
else
{
btr = tr.GetObject(bref.BlockTableRecord,OpenMode.ForRead) as BlockTableRecord;
}
}
Point3d insPt = attref.Position.TransformBy(bref.BlockTransform);
btr.UpgradeOpen();
ObjectIdCollection bids = new ObjectIdCollection();
AttributeDefinition def = null;
foreach (ObjectId defid in btr)
{
if (defid.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(AttributeDefinition))))
{
def = tr.GetObject(defid, OpenMode.ForRead) as AttributeDefinition;
if (def.Tag == attref.Tag)
{
def.UpgradeOpen();
bids.Add(defid);
break;
}
}
}
IdMapping map = new IdMapping();
db.DeepCloneObjects(bids, btr.ObjectId, map,true);
ObjectIdCollection coll = new ObjectIdCollection();
AttributeDefinition attDef = null;
foreach (IdPair pair in map)
{
if (pair.IsPrimary)
{
Entity oent = (Entity)tr.GetObject(pair.Value, OpenMode.ForWrite);
if (oent != null)
{
if (pair.Value.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(AttributeDefinition))))
{
attDef = oent as AttributeDefinition;
attDef.UpgradeOpen();
attDef.SetPropertiesFrom(def as Entity);
// add other properties from source attribute definition to suit here:
attDef.Justify = def.Justify;
attDef.Position = btr.Origin.Add(
new Vector3d(attDef.Position.X, attDef.Position.Y - attDef.Height * 1.25, attDef.Position.Z)).TransformBy(Matrix3d.Identity
);
attDef.Tag = "NEW_TAG";
attDef.TextString = "New Prompt";
attDef.TextString = "New Textstring";
coll.Add(oent.ObjectId);
}
}
}
}
btr.AssumeOwnershipOf(coll);
btr.DowngradeOpen();
attDef.Dispose();//optional
bref.RecordGraphicsModified(true);
tr.TransactionManager.QueueForGraphicsFlush();
doc.TransactionManager.FlushGraphics();//optional
ed.UpdateScreen();
tr.Commit();
}
}
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.Message + "\n" + ex.StackTrace);
}
finally
{
acadApp.ShowAlertDialog("Call command \"ATTSYNC\" manually");
}
}
'/**
'* Pedir al usuario donde y con que angulo, para insertar el bloque indicado en el plano abierto en ese momento.
'*/
Public Shared Sub InsertarBloque(ByVal archivoDWG As String)
Dim acadDoc As Document
acadDoc = Application.DocumentManager.MdiActiveDocument
Using acadLockDoc As DocumentLock = acadDoc.LockDocument()
Dim dbTemporal As Database
dbTemporal = New Database(buildDefaultDrawing:=False, noDocument:=True)
dbTemporal.ReadDwgFile(fileName:=archivoDWG, _
fileSharing:=IO.FileShare.Read, _
allowCPConversion:=False, _
password:="")
Dim nombreBloque As String
nombreBloque = IO.Path.GetFileNameWithoutExtension(archivoDWG)
SymbolUtilityServices.ValidateSymbolName(name:=nombreBloque, allowVerticalBar:=False)
Dim acadDB As Database
acadDB = acadDoc.Database
Dim idBloque As ObjectId
idBloque = acadDB.Insert(blockName:=nombreBloque, dataBase:=dbTemporal, preserveSourceDatabase:=False)
Dim bloqueAInsertar As BlockReference
bloqueAInsertar = New BlockReference(position:=Point3d.Origin, BlockTableRecord:=idBloque)
Dim acadEditor As Editor
acadEditor = acadDoc.Editor
bloqueAInsertar.TransformBy(acadEditor.CurrentUserCoordinateSystem)
Dim unaPlantilla As PlantillaBloque_PedirPuntoDeInserccion
unaPlantilla = New PlantillaBloque_PedirPuntoDeInserccion(bloqueAInsertar)
Dim resultadoPedirPunto As PromptResult
resultadoPedirPunto = acadEditor.Drag(unaPlantilla)
If resultadoPedirPunto.Status.Equals(PromptStatus.OK) Then
Dim otraPlantilla As PlantillaBloque_PedirAnguloDeRotacion
otraPlantilla = New PlantillaBloque_PedirAnguloDeRotacion(bloqueAInsertar, _
anguloBase:=bloqueAInsertar.Rotation, _
sistemaCoordenadas:=acadEditor.CurrentUserCoordinateSystem.CoordinateSystem3d, _
puntoBase:=unaPlantilla.getPuntoDeInsercion)
Dim resultadoPedirAngulo As PromptResult
resultadoPedirAngulo = acadEditor.Drag(otraPlantilla)
If resultadoPedirAngulo.Status.Equals(PromptStatus.OK) Then
otraPlantilla.ActualizarRotacion()
Else
bloqueAInsertar.Rotation = 0.0
End If
Using acadTrans As Transaction = acadDoc.TransactionManager.StartTransaction
Dim espacioActual As BlockTableRecord
espacioActual = CType(acadTrans.GetObject(acadDoc.Database.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
espacioActual.AppendEntity(entity:=bloqueAInsertar)
acadTrans.AddNewlyCreatedDBObject(obj:=bloqueAInsertar, add:=True)
Dim bloque As BlockTableRecord
bloque = CType(acadTrans.GetObject(idBloque, OpenMode.ForWrite), BlockTableRecord)
If bloque.HasAttributeDefinitions Then
Dim idElemento As ObjectId
For Each idElemento In bloque
Dim elemento As DBObject
elemento = acadTrans.GetObject(idElemento, OpenMode.ForRead)
If elemento.GetType.Name.Equals("AttributeDefinition") Then
Dim definicionDeAtributo As AttributeDefinition
definicionDeAtributo = CType(acadTrans.GetObject(idElemento, OpenMode.ForRead), AttributeDefinition)
Dim referenciaAAtributo As AttributeReference
referenciaAAtributo = New AttributeReference
referenciaAAtributo.SetAttributeFromBlock(definicionDeAtributo, bloqueAInsertar.BlockTransform)
bloqueAInsertar.AttributeCollection.AppendAttribute(referenciaAAtributo)
acadTrans.AddNewlyCreatedDBObject(obj:=referenciaAAtributo, add:=True)
End If
Next
End If
acadTrans.Commit()
End Using '//acadTrans
End If
End Using '//acadLockDoc
Application.UpdateScreen()
End Sub
Friend Class PlantillaBloque_PedirPuntoDeInserccion
Inherits Autodesk.Autocad.EditorInput.EntityJig
Dim mPuntoDeInsercion, mPuntoActivo As Point3d
Public Sub New(bloqueAInsertar as BlockReference)
MyBase.New(bloqueAInsertar)
mPuntoDeInsercion = bloqueAInsertar.Position
End Sub
Protected Overrides Function Sampler(ByVal prompts As Autodesk.AutoCAD.EditorInput.JigPrompts) As Autodesk.AutoCAD.EditorInput.SamplerStatus
Dim opciones As New JigPromptPointOptions
opciones.UserInputControls = UserInputControls.Accept3dCoordinates or _
UserInputControls.NoZeroResponseAccepted or _
UserInputControls.NoNegativeResponseAccepted
opciones.Message = environment.NewLine & "Punto de insercion: "
Dim resultado As PromptPointResult
resultado = prompts.AcquirePoint(opciones)
If mPuntoActivo = resultado.Value Then
Return SamplerStatus.NoChange
Else
mPuntoActivo = resultado.Value
Return SamplerStatus.OK
End If
End Function
Protected Overrides Function Update() As Boolean
mPuntoDeInsercion = mPuntoActivo
Try
CType(Entity, BlockReference).Position = mPuntoDeInsercion
Catch ex As Exception
Return False
End Try
Return True
End Function
Public Function getEntity As Entity
Return Entity
End Function
Public Function getPuntoDeInsercion As Point3d
Return mPuntoDeInsercion
End Function
End Class
Friend Class PlantillaBloque_PedirAnguloDeRotacion
Inherits Autodesk.Autocad.EditorInput.EntityJig
Dim mEntidadARotar As BlockReference
Dim mAnguloBase, mVariacionAngulo As Double
Dim mSistemaDeCoordenadas As CoordinateSystem3d
Dim mPuntoBase As Point3d
Dim mResultado As string
Public Sub New(bloqueAInsertar as BlockReference, _
anguloBase As Double, _
sistemaCoordenadas As CoordinateSystem3d, _
puntoBase As Point3d)
MyBase.New(bloqueAInsertar)
mEntidadARotar = bloqueAInsertar
mAnguloBase = anguloBase
mSistemaDeCoordenadas = sistemaCoordenadas
mPuntoBase = puntoBase
End Sub
Protected Overrides Function Sampler(ByVal prompts As Autodesk.AutoCAD.EditorInput.JigPrompts) As Autodesk.AutoCAD.EditorInput.SamplerStatus
Dim opciones As New JigPromptAngleOptions
opciones.Message = environment.NewLine & "Angulo a rotar: "
opciones.DefaultValue = 0
opciones.BasePoint = mPuntoBase
opciones.UseBasePoint = True
opciones.UserInputControls=UserInputControls.Accept3dCoordinates or UserInputControls.NullResponseAccepted
Dim resultado As PromptDoubleResult
resultado = prompts.AcquireAngle(opciones)
If resultado.Status = PromptStatus.OK Then
mResultado = resultado.StringResult
If mVariacionAngulo = resultado.Value Then
Return SamplerStatus.NoChange
Else
mVariacionAngulo = resultado.Value
Return SamplerStatus.OK
End If
End If
Return SamplerStatus.Cancel
End Function
Protected Overrides Function Update() As Boolean
mEntidadARotar.Rotation = mVariacionAngulo + mAnguloBase
Return True
End Function
Public Sub ActualizarRotacion
mEntidadARotar.Rotation = mVariacionAngulo + mAnguloBase
End Sub
Public Function getEntity As Entity
Return Entity
End Function
Public Function getAnguloDeRotacion As Double
Return mAnguloBase
End Function
Public Function getResultado As String
Return mResultado
End Function
End Class
public ObjectIdCollection GetModelSpaceBlockReferenceOIDCByBlockName(string blockReferenceName)
{
ObjectIdCollection returnOIDs = new ObjectIdCollection();
using (Database db = AcadApp.DocumentManager.MdiActiveDocument.Database)
{
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btrModel = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
foreach (ObjectId thisOid in btrModel)
{
Entity blk = (Entity)trans.GetObject(thisOid, OpenMode.ForRead);
if (blk.GetType().ToString() == "Autodesk.AutoCAD.DatabaseServices.BlockReference")
{
BlockReference thisBlockRef = (BlockReference)trans.GetObject(thisOid, OpenMode.ForRead);
if(string.Compare(thisBlockRef.Name, blockReferenceName, true) == 0)
{
returnOIDs.Add(thisOid);
}
}
}
return returnOIDs;
}
}
}
Hi,
Here's a little example for attributes extraction.
I try to write it in a "declarative" style using the Linq extension methods and some others defined in the Extension class (thanks to Thorsten 'kaefer' @ TheSwamp for its nice 'evil' ones).
[...snip..]
The Extensions class provides extension methods that allows to write code in a more "declarative" style
and methods to build a DataTable from a BlockAttribute collection and convert this DataTable into xls, csv files or AutoCAD Table.Code: [Select]using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using AcDataTable = Autodesk.AutoCAD.DatabaseServices.DataTable;
namespace AttributeExtraction
{
public static class Extensions
{
// Opens a DBObject in ForRead mode (kaefer @ TheSwamp)
public static T GetObject<T>(this ObjectId id) where T : DBObject
{
return id.GetObject<T>(OpenMode.ForRead);
}
// Opens a DBObject in the given mode (kaefer @ TheSwamp)
public static T GetObject<T>(this ObjectId id, OpenMode mode) where T : DBObject
{
return id.GetObject(mode) as T;
}
// Opens a collection of DBObject in ForRead mode (kaefer @ TheSwamp)
public static IEnumerable<T> GetObjects<T>(this IEnumerable ids) where T : DBObject
{
return ids.GetObjects<T>(OpenMode.ForRead);
}
// Opens a collection of DBObject in the given mode (kaefer @ TheSwamp)
public static IEnumerable<T> GetObjects<T>(this IEnumerable ids, OpenMode mode) where T : DBObject
{
return ids
.Cast<ObjectId>()
.Select(id => id.GetObject<T>(mode))
.Where(res => res != null);
}
// Applies the given Action to each element of the collection (mimics the F# Seq.iter function).
public static void Iterate<T>(this IEnumerable<T> collection, Action<T> action)
{
foreach (T item in collection) action(item);
}
// Applies the given Action to each element of the collection (mimics the F# Seq.iteri function).
// The integer passed to the Action indicates the index of element.
public static void Iterate<T>(this IEnumerable<T> collection, Action<T, int> action)
{
int i = 0;
foreach (T item in collection) action(item, i++);
}
// Gets the block effective name (anonymous dynamic blocs).
public static string GetEffectiveName(this BlockReference br)
{
if (br.IsDynamicBlock)
return br.DynamicBlockTableRecord.GetObject<BlockTableRecord>().Name;
return br.Name;
}
// Creates a System.Data.DataTable from a BlockAttribute collection.
public static System.Data.DataTable ToDataTable(this IEnumerable<BlockAttribute> blockAtts, string name)
{
System.Data.DataTable dTable = new System.Data.DataTable(name);
dTable.Columns.Add("Name", typeof(string));
dTable.Columns.Add("Quantity", typeof(int));
blockAtts
.GroupBy(blk => blk, (blk, blks) => new { Block = blk, Count = blks.Count() }, new BlockAttributeEqualityComparer())
.Iterate(row =>
{
System.Data.DataRow dRow = dTable.Rows.Add(row.Block.Name, row.Count);
row.Block.Attributes.Iterate(att =>
{
if (!dTable.Columns.Contains(att.Key))
dTable.Columns.Add(att.Key);
dRow[att.Key] = att.Value;
});
});
return dTable;
}
// Gets the column names collection of the datatable
public static IEnumerable<string> GetColumnNames(this System.Data.DataTable dataTbl)
{
return dataTbl.Columns.Cast<System.Data.DataColumn>().Select(col => col.ColumnName);
}
// Writes an Excel file from the datatable (using late binding)
public static void WriteXls(this System.Data.DataTable dataTbl, string filename, string sheetName, bool visible)
{
object mis = Type.Missing;
object xlApp = LateBinding.GetOrCreateInstance("Excel.Application");
xlApp.Set("DisplayAlerts", false);
object workbooks = xlApp.Get("Workbooks");
object workbook, worksheet;
if (File.Exists(filename))
workbook = workbooks.Invoke("Open", filename);
else
workbook = workbooks.Invoke("Add", mis);
if (string.IsNullOrEmpty(sheetName))
worksheet = workbook.Get("Activesheet");
else
{
object worksheets = workbook.Get("Worksheets");
try
{
worksheet = worksheets.Get("Item", sheetName);
worksheet.Get("Cells").Invoke("Clear");
}
catch
{
worksheet = worksheets.Invoke("Add", mis);
worksheet.Set("Name", sheetName);
}
}
object range = worksheet.Get("Cells");
dataTbl.GetColumnNames()
.Iterate((name, i) => range.Get("Item", 1, i + 1).Set("Value2", name));
dataTbl.Rows
.Cast<DataRow>()
.Iterate((row, i) => row.ItemArray
.Iterate((item, j) => range.Get("Item", i + 2, j + 1).Set("Value2", item)));
xlApp.Set("DisplayAlerts", true);
if (visible)
{
xlApp.Set("Visible", true);
}
else
{
if (File.Exists(filename))
workbook.Invoke("Save");
else
{
int fileFormat =
string.Compare("11.0", (string)xlApp.Get("Version")) < 0 &&
filename.EndsWith(".xlsx", StringComparison.CurrentCultureIgnoreCase) ?
51 : -4143;
workbook.Invoke("Saveas", filename, fileFormat, string.Empty, string.Empty, false, false, 1, 1);
}
workbook.Invoke("Close");
workbook = null;
xlApp.ReleaseInstance();
xlApp = null;
}
}
// Writes a csv file from the datatable.
public static void WriteCsv(this System.Data.DataTable dataTbl, string filename)
{
using (StreamWriter writer = new StreamWriter(filename))
{
writer.WriteLine(dataTbl.GetColumnNames().Aggregate((s1, s2) => string.Format("{0},{1}", s1, s2)));
dataTbl.Rows
.Cast<DataRow>()
.Select(row => row.ItemArray.Aggregate((s1, s2) => string.Format("{0},{1}", s1, s2)))
.Iterate(line => writer.WriteLine(line));
}
}
// Creates an AutoCAD Table from the datatable.
public static Table ToAcadTable(this System.Data.DataTable dataTbl, double rowHeight, double columnWidth)
{
//return dataTbl.Rows.Cast<DataRow>().ToAcadTable(dataTbl.TableName, dataTbl.GetColumnNames(), rowHeight, columnWidth);
Table tbl = new Table();
tbl.Rows[0].Height = rowHeight;
tbl.Columns[0].Width = columnWidth;
tbl.InsertColumns(0, columnWidth, dataTbl.Columns.Count - 1);
tbl.InsertRows(0, rowHeight, dataTbl.Rows.Count + 1);
tbl.Cells[0, 0].Value = dataTbl.TableName;
dataTbl.GetColumnNames()
.Iterate((name, i) => tbl.Cells[1, i].Value = name);
dataTbl.Rows
.Cast<DataRow>()
.Iterate((row, i) =>
row.ItemArray.Iterate((item, j) =>
tbl.Cells[i + 2, j].Value = item));
return tbl;
}
}
}
Hi,
This is a simple and 'brute force' method to mimic the ATTSYNC command. It replaces the existing AttributeReferences from the inserted BlockReferences with new ones from the BlockTableRecord AttributeDefinitions.
The SynchronizeAttributes() method is defined as an extension method for the BlockTableRecord type so that it can be called as an instance method of this type.
Using example (assuming btr is a BlocTableRecord instance) : btr.SynchronizeAttributes()
<EDIT: corrected an issue w/ attributes in dynamic blocks>
<EDIT: corrected an issue w/ constant attributes>
C# codeCode - C#: [Select]
using System; using System.Collections.Generic; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Runtime; using AcRx = Autodesk.AutoCAD.Runtime; namespace Autodesk.AutoCAD.DatabaseServices { public static class ExtensionMethods { public static void SynchronizeAttributes(this BlockTableRecord target) { if (target == null) Transaction tr = target.Database.TransactionManager.TopTransaction; if (tr == null) List<AttributeDefinition> attDefs = target.GetAttributes(tr); foreach (ObjectId id in target.GetBlockReferenceIds(true, false)) { BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite); br.ResetAttributes(attDefs, tr); } if (target.IsDynamicBlock) { target.UpdateAnonymousBlocks(); foreach (ObjectId id in target.GetAnonymousBlockIds()) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead); attDefs = btr.GetAttributes(tr); foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false)) { BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForWrite); br.ResetAttributes(attDefs, tr); } } } } private static List<AttributeDefinition> GetAttributes(this BlockTableRecord target, Transaction tr) { foreach (ObjectId id in target) { if (id.ObjectClass == attDefClass) { AttributeDefinition attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead); attDefs.Add(attDef); } } return attDefs; } private static void ResetAttributes(this BlockReference br, List<AttributeDefinition> attDefs, Transaction tr) { foreach (ObjectId id in br.AttributeCollection) { if (!id.IsErased) { AttributeReference attRef = (AttributeReference)tr.GetObject(id, OpenMode.ForWrite); attValues.Add(attRef.Tag, attRef.IsMTextAttribute ? attRef.MTextAttribute.Contents : attRef.TextString); attRef.Erase(); } } foreach (AttributeDefinition attDef in attDefs) { attRef.SetAttributeFromBlock(attDef, br.BlockTransform); if (attDef.Constant) { attRef.TextString = attDef.IsMTextAttributeDefinition ? attDef.MTextAttributeDefinition.Contents : attDef.TextString; } else if (attValues.ContainsKey(attRef.Tag)) { attRef.TextString = attValues[attRef.Tag]; } br.AttributeCollection.AppendAttribute(attRef); tr.AddNewlyCreatedDBObject(attRef, true); } } } }
VB code (have to clear the Root Namespace in the project to add these extension methods to Autodesk.AutoCAD.DatabaseServices)Code - vb.net: [Select]
Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.Runtime Namespace Autodesk.AutoCAD.DatabaseServices Public Module ExtensionMethods Dim attDefClass As RXClass = RXClass.GetClass(GetType(AttributeDefinition)) <System.Runtime.CompilerServices.Extension> _ Public Sub SynchronizeAttributes(target As BlockTableRecord) If target Is Nothing Then Throw New ArgumentNullException("target") End If Dim tr As Transaction = target.Database.TransactionManager.TopTransaction If tr Is Nothing Then Throw New Exception(ErrorStatus.NoActiveTransactions) End If Dim attDefs As List(Of AttributeDefinition) = target.GetAttributes(tr) For Each id As ObjectId In target.GetBlockReferenceIds(True, False) Dim br As BlockReference = _ DirectCast(tr.GetObject(id, OpenMode.ForWrite), BlockReference) br.ResetAttributes(attDefs, tr) Next If target.IsDynamicBlock Then target.UpdateAnonymousBlocks() For Each id As ObjectId In target.GetAnonymousBlockIds() Dim btr As BlockTableRecord = _ DirectCast(tr.GetObject(id, OpenMode.ForRead), BlockTableRecord) attDefs = btr.GetAttributes(tr) For Each brId As ObjectId In btr.GetBlockReferenceIds(True, False) Dim br As BlockReference = _ DirectCast(tr.GetObject(brId, OpenMode.ForWrite), BlockReference) br.ResetAttributes(attDefs, tr) Next Next End If End Sub <System.Runtime.CompilerServices.Extension> _ Private Function GetAttributes(target As BlockTableRecord, tr As Transaction) As List(Of AttributeDefinition) Dim attdefs As List(Of AttributeDefinition) = New List(Of AttributeDefinition) For Each id As ObjectId In target If id.ObjectClass = attDefClass Then Dim attDef As AttributeDefinition = _ DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition) attdefs.Add(attDef) End If Next Return attdefs End Function <System.Runtime.CompilerServices.Extension> _ Private Sub ResetAttributes(br As BlockReference, attDefs As List(Of AttributeDefinition), tr As Transaction) Dim attValues As New Dictionary(Of String, String)() For Each id As ObjectId In br.AttributeCollection If Not id.IsErased Then Dim attRef As AttributeReference = _ DirectCast(tr.GetObject(id, OpenMode.ForWrite), AttributeReference) attValues.Add( _ attRef.Tag, _ If(attRef.IsMTextAttribute, attRef.MTextAttribute.Contents, attRef.TextString)) attRef.Erase() End If Next For Each attDef As AttributeDefinition In attDefs Dim attRef As New AttributeReference() attRef.SetAttributeFromBlock(attDef, br.BlockTransform) If attDef.Constant Then attRef.TextString = If(attDef.IsMTextAttributeDefinition, _ attDef.MTextAttributeDefinition.Contents, _ attDef.TextString) Else If attValues IsNot Nothing AndAlso attValues.ContainsKey(attDef.Tag) Then attRef.TextString = attValues(attDef.Tag.ToUpper()) End If br.AttributeCollection.AppendAttribute(attRef) tr.AddNewlyCreatedDBObject(attRef, True) Next End Sub End Module End Namespace
// Get the current UCS Z axis (extrusion direction)
Matrix3d ucsMat = ed.CurrentUserCoordinateSystem;
CoordinateSystem3d ucs = ucsMat.CoordinateSystem3d;
Vector3d zdir = ucsMat.CoordinateSystem3d.Zaxis;
// Get the OCS corresponding to UCS Z axis
Matrix3d ocsMat = MakeOcs(zdir);
// Transform the input point from UCS to OCS
//Point3d pt = ppr.Value.TransformBy(ucsMat.PreMultiplyBy(ocsMat));
// Get the X axis of the OCS
Vector3d ocsXdir = ocsMat.CoordinateSystem3d.Xaxis;
// Get the UCS rotation (angle between the OCS X axis and the UCS X axis)
double rot = ocsXdir.GetAngleTo(ucs.Xaxis, zdir);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
// Foreach in points collection
foreach (Point3d item in _pcIns)
{
BlockReference br = new BlockReference(item, bt["MDF"]);
br.Position = item;
br.Rotation = rot;
br.Normal = zdir;
btr.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
}
ObjectIdCollection brefIds = btr.GetBlockReferenceIds(false, true);
foreach (ObjectId id in brefIds)
{
BlockReference bref = (BlockReference)tr.GetObject(id, OpenMode.ForWrite, false, true);
bref.RecordGraphicsModified(true);
}
btr.SynchronizeAttributes();
tr.Commit();
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
if (!bt.Has("MDF"))
{
ed.WriteMessage("\nBloco modelo não localizado.");
return;
}
// Get the current UCS Z axis (extrusion direction)
Matrix3d ucsMat = ed.CurrentUserCoordinateSystem;
CoordinateSystem3d ucs = ucsMat.CoordinateSystem3d;
Vector3d zdir = ucsMat.CoordinateSystem3d.Zaxis;
// Get the OCS corresponding to UCS Z axis
Matrix3d ocsMat = MakeOcs(zdir);
// Transform the input point from UCS to OCS
//Point3d pt = ppr.Value.TransformBy(ucsMat.PreMultiplyBy(ocsMat));
// Get the X axis of the OCS
Vector3d ocsXdir = ocsMat.CoordinateSystem3d.Xaxis;
// Get the UCS rotation (angle between the OCS X axis and the UCS X axis)
double rot = ocsXdir.GetAngleTo(ucs.Xaxis, zdir);
BlockTableRecord curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
// Foreach in points collection
foreach (PointsLocation item in _pcIns)
{
BlockReference br = new BlockReference(item._ponto, bt["MDF"]);
br.Position = item._ponto;
br.Rotation = rot;
br.Normal = zdir;
ObjectId _newid = curSpace.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
if (br.IsDynamicBlock && ids.Length == 2)
{
DynamicBlockReferencePropertyCollection props = br.DynamicBlockReferencePropertyCollection;
foreach (DynamicBlockReferenceProperty prop in props)
{
object[] values = prop.GetAllowedValues();
if (item._ordem == 0)
{
//Switch Property
switch (prop.PropertyName)
{
case "Distancia_Texto":
prop.Value = 18.0;
break;
case "Anglo_Texto":
prop.Value = 45.0;
break;
case "Anglo_Marco":
prop.Value = 0.0;
break;
}
}
else
{
switch (prop.PropertyName)
{
case "Distancia_Texto":
prop.Value = 18.0;
break;
case "Anglo_Texto":
prop.Value = 225.0;
break;
case "Anglo_Marco":
prop.Value = 0.0;
break;
}
}
}
}
}
var btr = (BlockTableRecord)tr.GetObject(bt["MDF"], OpenMode.ForRead);
btr.SynchronizeAttributes();
tr.Commit();