Create table of block attribute using c#

Create table of block attribute using c#

Anonymous
Not applicable
3,826 Views
6 Replies
Message 1 of 7

Create table of block attribute using c#

Anonymous
Not applicable

This is my code which return me a table in which heading is attribute.tag and content is attribute.textstring. In my block there is 5 attribute tags i.e.

  1. Sheetno
  2. Scale

3.Taildrg

4.Headdrg

5.Dtlno.

But when table is shown there is only one Tag shown in the header section i.e.Sheetno and in the header section my first record is shown. please suggest me the solution for same.And also i want to choose a block by choosing whole page and then filter the right one block and shown there table.

Below is my dwg file and screenshot of output. Thanx in advance.

 

Snippet

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System.Collections.Specialized;
 
namespace TableCreation
{
    public class Commands
    {
        // Set up some formatting constants
        // for the table
 
        private const double colWidth = 15.0;
        private const double rowHeight = 3.0;
        private const double textHeight = 1.0;
 
        private const CellAlignment cellAlign =
          CellAlignment.MiddleCenter;
 
        // Helper function to set text height
        // and alignment of specific cells,
        // as well as inserting the text
 
        static public void SetCellText(Table tb, int row, int col, string value)
        {
            tb.SetAlignment(row, col, cellAlign);
            tb.SetTextHeight(row, col, textHeight);
            tb.SetTextString(row, col, value);
        }
 
        [CommandMethod("BAT")]
        static public void BlockAttributeTable()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
 
            PromptStringOptions opt = new PromptStringOptions("\nEnter name of block to list: ");
            PromptResult pr = ed.GetString(opt);
 
            if (pr.Status == PromptStatus.OK)
            {
                string blockToFind = pr.StringResult.ToUpper();
 
                Transaction tr = doc.TransactionManager.StartTransaction();
                using (tr)
                {
                    // Let's check the block exists
 
                    BlockTable bt = (BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead);
 
                    if (!bt.Has(blockToFind))
                    {
                        ed.WriteMessage("\nBlock " + blockToFind + " does not exist.");
                    }
                    else
                    {
                        // And go through looking for
                        // attribute definitions
 
                        StringCollection colNames = new StringCollection();
 
                        BlockTableRecord bd = (BlockTableRecord)tr.GetObject(bt[blockToFind], OpenMode.ForRead);
                        foreach (ObjectId adId in bd)
                        {
                            DBObject adObj = tr.GetObject(adId, OpenMode.ForRead);
 
                            // For each attribute definition we find...
 
                            AttributeDefinition ad = adObj as AttributeDefinition;
                            if (ad != null)
                            {
                                // ... we add its name to the list
 
                                colNames.Add(ad.Tag);
                                ed.WriteMessage("\n" + ad.Tag);
                            }
                        }
                        if (colNames.Count == 0)
                        {
                            ed.WriteMessage("\nThe block " + blockToFind + " contains no attribute definitions.");
                        }
                        else
                        {
                            // Ask the user for the insertion point
                            // and then create the table
 
                            PromptPointResult ppr;
                            PromptPointOptions ppo = new PromptPointOptions("");
                            ppo.Message = "\n Select the place for print output:";
                            //get the coordinates from user
                            ppr = ed.GetPoint(ppo);
                            if (ppr.Status != PromptStatus.OK)
                                return;
                            Point3d startPoint = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);
                            //Point3d startPoint1 = startPoint.Subtract();
                            Vector3d disp = new Vector3d(0.0-2.0 * db.Textsize, 0.0);
                            Vector3d disp2 = new Vector3d(0.0-2.0 * db.Textsize, 0.0);
 
                            if (ppr.Status == PromptStatus.OK)
                            {
                                Table tb = new Table();
                                tb.TableStyle = db.Tablestyle;
                                tb.NumRows = 1;
                                tb.NumColumns = colNames.Count;
                                tb.SetRowHeight(rowHeight);
                                tb.SetColumnWidth(colWidth);
                                tb.Position = startPoint;
 
                                // Let's add our column headings
 
                                for (int i = 0; i < 5; i++)
                                {
                                    SetCellText(tb, 0, i, colNames[i]);
                                    //ed.WriteMessage("\n" + colNames[i]);
                                }
 
                                // Now let's search for instances of
                                // our block in the modelspace
 
                                BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.PaperSpace], OpenMode.ForRead);
 
                                int rowNum = 1;
                                foreach (ObjectId objId in ms)
                                {
                                    DBObject obj = tr.GetObject(objId, OpenMode.ForRead);
                                    BlockReference br = obj as BlockReference;
                                    if (br != null)
                                    {
                                        BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead);
                                        using (btr)
                                        {
                                            if (btr.Name.ToUpper() == blockToFind)
                                            {
                                                // We have found one of our blocks,
                                                // so add a row for it in the table
 
                                                tb.InsertRows(rowNum, rowHeight, 2);
 
                                                // Assume that the attribute refs
                                                // follow the same order as the
                                                // attribute defs in the block
 
                                                int attNum = 0;
                                                foreach (ObjectId arId in br.AttributeCollection)
                                                {
                                                    DBObject arObj = tr.GetObject(arId, OpenMode.ForRead);
                                                    AttributeReference ar = arObj as AttributeReference;
                                                    if (ar != null)
                                                    {
                                                        string strCell;
 
                                                        strCell = ar.TextString;
 
                                                        string strArId = arId.ToString();
 
                                                        strArId = strArId.Trim(new char[] { '('')' });
 
                                                        SetCellText(tb, rowNum, attNum, strCell);
                                                        ed.WriteMessage("\n" + ar.Tag);
                                                    }
                                                    attNum++;
                                                }
                                                rowNum++;
                                            }
                                        }
                                    }
                                }
                                tb.GenerateLayout();
 
                                ms.UpgradeOpen();
                                ms.AppendEntity(tb);
                                tr.AddNewlyCreatedDBObject(tb, true);
                                tr.Commit();
                            }
                        }
                    }
                }
            }
        }
    }
}

 

0 Likes
Accepted solutions (1)
3,827 Views
6 Replies
Replies (6)
Message 2 of 7

_gile
Consultant
Consultant

Hi,

 

This is due to the current table style (db.Tablestyle) in which the first row is a 'title' row (merged cells).

You can use it to display the block name and use the second row for the headers

 

        // Set up some formatting constants
        // for the table

        private const double colWidth = 15.0;
        private const double rowHeight = 3.0;
        private const double textHeight = 1.0;
        private const CellAlignment cellAlign = CellAlignment.MiddleCenter;

        // Helper function to set text height
        // and alignment of specific cells,
        // as well as inserting the text

        static public void SetCellText(Table tb, int row, int col, string value)
        {
            tb.Cells[row, col].Alignment = cellAlign;
            tb.Cells[row, col].TextHeight = textHeight;
            tb.Cells[row, col].Value = value;
        }

        [CommandMethod("BAT")]
        static public void BlockAttributeTable()
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptStringOptions opt = new PromptStringOptions("\nEnter name of block to list: ");
            PromptResult pr = ed.GetString(opt);

            if (pr.Status == PromptStatus.OK)
            {
                string blockToFind = pr.StringResult.ToUpper();

                Transaction tr = doc.TransactionManager.StartTransaction();
                using (tr)
                {
                    // Let's check the block exists

                    BlockTable bt = (BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead);

                    if (!bt.Has(blockToFind))
                    {
                        ed.WriteMessage("\nBlock " + blockToFind + " does not exist.");
                    }
                    else
                    {
                        // And go through looking for
                        // attribute definitions

                        StringCollection colNames = new StringCollection();

                        BlockTableRecord bd = (BlockTableRecord)tr.GetObject(bt[blockToFind], OpenMode.ForRead);
                        foreach (ObjectId adId in bd)
                        {
                            DBObject adObj = tr.GetObject(adId, OpenMode.ForRead);

                            // For each attribute definition we find...

                            AttributeDefinition ad = adObj as AttributeDefinition;
                            if (ad != null)
                            {
                                // ... we add its name to the list

                                colNames.Add(ad.Tag);
                                ed.WriteMessage("\n" + ad.Tag);
                            }
                        }
                        if (colNames.Count == 0)
                        {
                            ed.WriteMessage("\nThe block " + blockToFind + " contains no attribute definitions.");
                        }
                        else
                        {
                            // Ask the user for the insertion point
                            // and then create the table

                            PromptPointResult ppr;
                            PromptPointOptions ppo = new PromptPointOptions("");
                            ppo.Message = "\n Select the place for print output:";
                            //get the coordinates from user
                            ppr = ed.GetPoint(ppo);
                            if (ppr.Status != PromptStatus.OK)
                                return;
                            Point3d startPoint = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);
                            //Point3d startPoint1 = startPoint.Subtract();
                            Vector3d disp = new Vector3d(0.0, -2.0 * db.Textsize, 0.0);
                            Vector3d disp2 = new Vector3d(0.0, -2.0 * db.Textsize, 0.0);

                            if (ppr.Status == PromptStatus.OK)
                            {
                                Table tb = new Table();
                                tb.TableStyle = db.Tablestyle;
                                tb.SetSize(2, colNames.Count);
                                tb.SetRowHeight(rowHeight);
                                tb.SetColumnWidth(colWidth);
                                tb.Position = startPoint;

                                // Let's add the table title
                                tb.Cells[0, 0].Value = bd.Name;

                                // Let's add our column headings

                                for (int i = 0; i < colNames.Count; i++)
                                {
                                    SetCellText(tb, 1, i, colNames[i]);
                                    //ed.WriteMessage("\n" + colNames[i]);
                                }

                                // Now let's search for instances of
                                // our block in the modelspace

                                ObjectId msId = SymbolUtilityServices.GetBlockModelSpaceId(db);
                                BlockTableRecord ms = (BlockTableRecord)tr.GetObject(msId, OpenMode.ForWrite);

                                int rowNum = 2;
                                foreach (ObjectId brId in bd.GetBlockReferenceIds(true, true))
                                {
                                    BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
                                    if (br.OwnerId == msId)
                                    {
                                        // We have found one of our blocks,
                                        // so add a row for it in the table

                                        tb.InsertRows(rowNum, rowHeight, 1);

                                        // Assume that the attribute refs
                                        // follow the same order as the
                                        // attribute defs in the block

                                        int attNum = 0;
                                        foreach (ObjectId arId in br.AttributeCollection)
                                        {
                                            DBObject arObj = tr.GetObject(arId, OpenMode.ForRead);
                                            AttributeReference ar = arObj as AttributeReference;
                                            if (ar != null)
                                            {
                                                string strCell = ar.TextString;

                                                string strArId = arId.ToString().Trim('(', ')');

                                                SetCellText(tb, rowNum, attNum, strCell);
                                                ed.WriteMessage("\n" + ar.Tag);
                                            }
                                            attNum++;
                                        }
                                        rowNum++;
                                    }
                                }
                                tb.GenerateLayout();

                                ms.AppendEntity(tb);
                                tr.AddNewlyCreatedDBObject(tb, true);
                                tr.Commit();
                            }
                        }
                    }
                }
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 7

Anonymous
Not applicable
Accepted solution
What if i dont want to type block name manually,i want to select a block and according to that block name print table for the same block in the dwg.
0 Likes
Message 4 of 7

_gile
Consultant
Consultant

Hi

 

You can use Editor.GetEntity() instead of Editor.GetString() for the user input. Then, open the block reference within the transaction and directly get its block table record with BlockReference.BlockTableRecord property.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 7

Anonymous
Not applicable
Can you please edit this in my solution?
0 Likes
Message 6 of 7

_gile
Consultant
Consultant

Sorry, I thought you wanted to learn rather than wanting someone to do your work.

 

Here's "your" edited solution:

 

        // Set up some formatting constants
        // for the table

        private const double colWidth = 15.0;
        private const double rowHeight = 3.0;
        private const double textHeight = 1.0;
        private const CellAlignment cellAlign = CellAlignment.MiddleCenter;

        // Helper function to set text height
        // and alignment of specific cells,
        // as well as inserting the text

        static public void SetCellText(Table tb, int row, int col, string value)
        {
            tb.Cells[row, col].Alignment = cellAlign;
            tb.Cells[row, col].TextHeight = textHeight;
            tb.Cells[row, col].Value = value;
        }

        [CommandMethod("BAT")]
        static public void BlockAttributeTable()
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            var options = new PromptEntityOptions("\nSelect a block: ");
            options.SetRejectMessage("\nMust be a block.");
            options.AddAllowedClass(typeof(BlockReference), true);
            var result = ed.GetEntity(options);

            if (result.Status == PromptStatus.OK)
            {
                using (Transaction tr = doc.TransactionManager.StartTransaction())
                {
                    // Let's get the block definition

                    BlockTable bt = (BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead);
                    BlockReference br = (BlockReference)tr.GetObject(result.ObjectId, OpenMode.ForRead);
                    BlockTableRecord bd = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead);
                    string blockName = bd.Name;

                    // And go through looking for
                    // attribute definitions

                    StringCollection colNames = new StringCollection();

                    foreach (ObjectId adId in bd)
                    {
                        DBObject adObj = tr.GetObject(adId, OpenMode.ForRead);

                        // For each attribute definition we find...

                        AttributeDefinition ad = adObj as AttributeDefinition;
                        if (ad != null)
                        {
                            // ... we add its name to the list

                            colNames.Add(ad.Tag);
                            ed.WriteMessage("\n" + ad.Tag);
                        }
                    }
                    if (colNames.Count == 0)
                    {
                        ed.WriteMessage("\nThe block " + blockName + " contains no attribute definitions.");
                    }
                    else
                    {
                        // Ask the user for the insertion point
                        // and then create the table

                        PromptPointResult ppr;
                        PromptPointOptions ppo = new PromptPointOptions("");
                        ppo.Message = "\n Select the place for print output:";
                        //get the coordinates from user
                        ppr = ed.GetPoint(ppo);
                        if (ppr.Status != PromptStatus.OK)
                            return;
                        Point3d startPoint = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);
                        //Point3d startPoint1 = startPoint.Subtract();
                        Vector3d disp = new Vector3d(0.0, -2.0 * db.Textsize, 0.0);
                        Vector3d disp2 = new Vector3d(0.0, -2.0 * db.Textsize, 0.0);

                        if (ppr.Status == PromptStatus.OK)
                        {
                            Table tb = new Table();
                            tb.TableStyle = db.Tablestyle;
                            tb.SetSize(2, colNames.Count);
                            tb.SetRowHeight(rowHeight);
                            tb.SetColumnWidth(colWidth);
                            tb.Position = startPoint;

                            // Let's add the table title
                            tb.Cells[0, 0].Value = bd.Name;

                            // Let's add our column headings

                            for (int i = 0; i < colNames.Count; i++)
                            {
                                SetCellText(tb, 1, i, colNames[i]);
                                //ed.WriteMessage("\n" + colNames[i]);
                            }

                            // Now let's search for instances of
                            // our block in the modelspace

                            ObjectId msId = SymbolUtilityServices.GetBlockModelSpaceId(db);
                            BlockTableRecord ms = (BlockTableRecord)tr.GetObject(msId, OpenMode.ForWrite);

                            int rowNum = 2;
                            foreach (ObjectId brId in bd.GetBlockReferenceIds(true, true))
                            {
                                br = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
                                if (br.OwnerId == msId)
                                {
                                    // We have found one of our blocks,
                                    // so add a row for it in the table

                                    tb.InsertRows(rowNum, rowHeight, 1);

                                    // Assume that the attribute refs
                                    // follow the same order as the
                                    // attribute defs in the block

                                    int attNum = 0;
                                    foreach (ObjectId arId in br.AttributeCollection)
                                    {
                                        DBObject arObj = tr.GetObject(arId, OpenMode.ForRead);
                                        AttributeReference ar = arObj as AttributeReference;
                                        if (ar != null)
                                        {
                                            string strCell = ar.TextString;

                                            string strArId = arId.ToString().Trim('(', ')');

                                            SetCellText(tb, rowNum, attNum, strCell);
                                            ed.WriteMessage("\n" + ar.Tag);
                                        }
                                        attNum++;
                                    }
                                    rowNum++;
                                }
                            }
                            tb.GenerateLayout();

                            ms.AppendEntity(tb);
                            tr.AddNewlyCreatedDBObject(tb, true);
                            tr.Commit();
                        }
                    }
                }
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 7

Anonymous
Not applicable
Thanx it works properly.
0 Likes