找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 981|回复: 0

[分享] Creating a table of block attributes in AutoCAD using .NET - Part 2

[复制链接]

已领礼包: 859个

财富等级: 财运亨通

发表于 2014-5-11 17:07:23 来自手机 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 csharp 于 2014-5-12 08:08 编辑

http://through-the-interface.typepad.com/through_the_interface/2007/06/creating_a_tabl.html

Creating a table of block attributes in AutoCAD using .NET - Part 2
In the last post we looked at some code to create a table of attribute values for a particular block. In this post we'll extend that code and show how to use a formula to create a total of those values.
Below is the C# code. I've numbered the lines, and those in red are new since the last post. The complete source file can be downloaded here.
Firstly, a quick breakdown of the changes:
  • Lines 60-81 deal with user input, and the forcing of the decision to "embed" rather than "link", if we're performing the total (table formulae do not work with fields, even if they have numeric results, so we're forced to create the table with the current value, rather than a field pointing to the attribute reference)
  • Line 134 and subsequently lines 159-166 declare and set a variable indicating for which column we're going to provide a total
  • Lines 169-181 deal with the exceptional case that we don't find the specified attribute definition
  • Lines 310-336 create our additional row, and insert the total in the appropriate cell. We're using a formula such as this: %<\AcExpr (Sum(A2:A4)) \f "%lu2%pr2">%
    • The \f flag specifies we want a numeric value with 2 decimal places - these codes are not documented, but you can find them out by using the FIELD command, as described in this previous post
  • Line 343 performs a regen, to update the value of our field
And now for the code:
    1 using Autodesk.AutoCAD.ApplicationServices;
    2 using Autodesk.AutoCAD.DatabaseServices;
    3 using Autodesk.AutoCAD.EditorInput;
    4 using Autodesk.AutoCAD.Geometry;
    5 using Autodesk.AutoCAD.Runtime;
    6 using System.Collections.Specialized;
    7 using System;
    8
    9 namespace TableCreation
   10 {
   11   public class Commands
   12   {
   13     // Set up some formatting constants
   14     // for the table
   15
   16     const double colWidth = 15.0;
   17     const double rowHeight = 3.0;
   18     const double textHeight = 1.0;
   19     const CellAlignment cellAlign =
   20       CellAlignment.MiddleCenter;
   21
   22     // Helper function to set text height
   23     // and alignment of specific cells,
   24     // as well as inserting the text
   25
   26     static public void SetCellText(
   27       Table tb,
   28       int row,
   29       int col,
   30       string value
   31     )
   32     {
   33       tb.SetAlignment(row, col, cellAlign);
   34       tb.SetTextHeight(row, col, textHeight);
   35       tb.SetTextString(row, col, value);
   36     }
   37
   38     [CommandMethod("BAT")]
   39     static public void BlockAttributeTable()
   40     {
   41       Document doc =
   42         Application.DocumentManager.MdiActiveDocument;
   43       Database db = doc.Database;
   44       Editor ed = doc.Editor;
   45
   46       // Ask for the name of the block to find
   47
   48       PromptStringOptions opt =
   49         new PromptStringOptions(
   50           "\nEnter name of block to list: "
   51         );
   52       PromptResult pr = ed.GetString(opt);
   53
   54       if (pr.Status == PromptStatus.OK)
   55       {
   56         string blockToFind =
   57           pr.StringResult.ToUpper();
   58         bool embed = false;
   59
   60         // And the attribute to provide total for
   61
   62         opt.Message =
   63           "\nEnter name of column to total <\"\">: ";
   64         pr = ed.GetString(opt);
   65
   66         if (pr.Status == PromptStatus.None ||
   67             pr.Status == PromptStatus.OK)
   68         {
   69           string columnToTotal =
   70               pr.StringResult.ToUpper();
   71
   72           if (columnToTotal != "")
   73           {
   74             // If a column has been chosen, we need
   75             // to embed the attribute values
   76             // as otherwise the "sum" formula will fail
   77
   78             embed = true;
   79           }
   80           else
   81           {
   82             // Ask whether to embed or link
   83
   84             PromptKeywordOptions pko =
   85               new PromptKeywordOptions(
   86                 "\nEmbed or link the attribute values: "
   87               );
   88
   89             pko.AllowNone = true;
   90             pko.Keywords.Add("Embed");
   91             pko.Keywords.Add("Link");
   92             pko.Keywords.Default = "Embed";
   93             PromptResult pkr =
   94               ed.GetKeywords(pko);
   95
   96             if (pkr.Status == PromptStatus.None ||
   97                 pkr.Status == PromptStatus.OK)
   98             {
   99               if (pkr.Status == PromptStatus.None ||
  100                   pkr.StringResult == "Embed")
  101                 embed = true;
  102               else
  103                 embed = false;
  104             }
  105           }
  106
  107           Transaction tr =
  108             doc.TransactionManager.StartTransaction();
  109           using (tr)
  110           {
  111             // Let's check the block exists
  112
  113             BlockTable bt =
  114               (BlockTable)tr.GetObject(
  115                 doc.Database.BlockTableId,
  116                 OpenMode.ForRead
  117               );
  118
  119             if (!bt.Has(blockToFind))
  120             {
  121               ed.WriteMessage(
  122                 "\nBlock "
  123                 + blockToFind
  124                 + " does not exist."
  125               );              
  126             }
  127             else
  128             {
  129               // And go through looking for
  130               // attribute definitions
  131
  132               StringCollection colNames =
  133                 new StringCollection();
  134               int colToTotalIdx = -1;
  135
  136               BlockTableRecord bd =
  137                 (BlockTableRecord)tr.GetObject(
  138                   bt[blockToFind],
  139                   OpenMode.ForRead
  140                 );
  141               foreach (ObjectId adId in bd)
  142               {
  143                 DBObject adObj =
  144                   tr.GetObject(
  145                     adId,
  146                     OpenMode.ForRead
  147                   );
  148
  149                 // For each attribute definition we find...
  150
  151                 AttributeDefinition ad =
  152                   adObj as AttributeDefinition;
  153                 if (ad != null)
  154                 {
  155                   // ... we add its name to the list
  156
  157                   colNames.Add(ad.Tag);
  158
  159                   if (ad.Tag.ToUpper() == columnToTotal)
  160                   {
  161                     // Save the index of the column
  162                     // we want to total
  163
  164                     colToTotalIdx =
  165                       colNames.Count - 1;
  166                   }
  167                 }
  168               }
  169               // If we didn't find the attribute to be totalled
  170               // then simply ignore the request and continue
  171
  172               if (columnToTotal != "" && colToTotalIdx < 0)
  173               {
  174                 ed.WriteMessage(
  175                   "\nAttribute definition for "
  176                   + columnToTotal
  177                   + " not found in "
  178                   + blockToFind
  179                   + ". Total will not be added to the table."
  180                 );
  181               }
  182               if (colNames.Count == 0)
  183               {
  184                 ed.WriteMessage(
  185                   "\nThe block "
  186                   + blockToFind
  187                   + " contains no attribute definitions."                  
  188                 );
  189               }
  190               else
  191               {
  192                 // Ask the user for the insertion point
  193                 // and then create the table
  194
  195                 PromptPointResult ppr =
  196                   ed.GetPoint(
  197                     "\nEnter table insertion point: "
  198                   );
  199
  200                 if (ppr.Status == PromptStatus.OK)
  201                 {
  202                   Table tb = new Table();
  203                   tb.TableStyle = db.Tablestyle;
  204                   tb.NumRows = 1;
  205                   tb.NumColumns = colNames.Count;
  206                   tb.SetRowHeight(rowHeight);
  207                   tb.SetColumnWidth(colWidth);
  208                   tb.Position = ppr.Value;
  209
  210                   // Let's add our column headings
  211
  212                   for (int i = 0; i < colNames.Count; i++)
  213                   {
  214                     SetCellText(tb, 0, i, colNames);
  215                   }
  216
  217                   // Now let's search for instances of
  218                   // our block in the modelspace
  219
  220                   BlockTableRecord ms =
  221                     (BlockTableRecord)tr.GetObject(
  222                       bt[BlockTableRecord.ModelSpace],
  223                       OpenMode.ForRead
  224                     );
  225
  226                   int rowNum = 1;
  227                   foreach (ObjectId objId in ms)
  228                   {
  229                     DBObject obj =
  230                       tr.GetObject(
  231                         objId,
  232                         OpenMode.ForRead
  233                       );
  234                     BlockReference br =
  235                       obj as BlockReference;
  236                     if (br != null)
  237                     {
  238                       BlockTableRecord btr =
  239                         (BlockTableRecord)tr.GetObject(
  240                           br.BlockTableRecord,
  241                           OpenMode.ForRead
  242                         );
  243                       using (btr)
  244                       {
  245                         if (btr.Name.ToUpper() == blockToFind)
  246                         {
  247                           // We have found one of our blocks,
  248                           // so add a row for it in the table
  249
  250                           tb.InsertRows(
  251                               rowNum,
  252                               rowHeight,
  253                               1
  254                           );
  255
  256                           // Assume that the attribute refs
  257                           // follow the same order as the
  258                           // attribute defs in the block
  259
  260                           int attNum = 0;
  261                           foreach (
  262                             ObjectId arId in
  263                             br.AttributeCollection
  264                           )
  265                           {
  266                             DBObject arObj =
  267                               tr.GetObject(
  268                                 arId,
  269                                 OpenMode.ForRead
  270                               );
  271                             AttributeReference ar =
  272                               arObj as AttributeReference;
  273                             if (ar != null)
  274                             {
  275                               // Embed or link the values
  276
  277                               string strCell;
  278                               if (embed)
  279                               {
  280                                 strCell = ar.TextString;
  281                               }
  282                               else
  283                               {
  284                                 string strArId =
  285                                   arId.ToString();
  286                                 strArId =
  287                                   strArId.Trim(
  288                                     new char[] { '(', ')' }
  289                                   );
  290                                 strCell =
  291                                   "%<\\AcObjProp Object("
  292                                     + "%<\\_ObjId "
  293                                     + strArId
  294                                     + ">%).TextString>%";
  295                               }
  296                               SetCellText(
  297                                 tb,
  298                                 rowNum,
  299                                 attNum,
  300                                 strCell
  301                               );
  302                             }
  303                             attNum++;
  304                           }
  305                           rowNum++;
  306                         }
  307                       }
  308                     }
  309                   }
  310
  311                   // Now let's add a row for our total
  312
  313                   if (colToTotalIdx >= 0)
  314                   {
  315                     tb.InsertRows(rowNum, rowHeight, 1);
  316                     char colLetter =
  317                       Convert.ToChar(
  318                         (Convert.ToInt32(
  319                           'A') + colToTotalIdx
  320                         )
  321                       );
  322
  323                     // Add a formula to sum the column
  324
  325                     SetCellText(
  326                       tb,
  327                       rowNum,
  328                       colToTotalIdx,
  329                       "%<\\AcExpr (Sum("
  330                         + colLetter
  331                         + "2:"
  332                         + colLetter
  333                         + rowNum.ToString()
  334                         + ")) \\f  \"%lu2%pr2\">%"
  335                     );
  336                   }
  337                   tb.GenerateLayout();
  338
  339                   ms.UpgradeOpen();
  340                   ms.AppendEntity(tb);
  341                   tr.AddNewlyCreatedDBObject(tb, true);
  342                   tr.Commit();
  343                   ed.Regen();
  344                 }
  345               }
  346             }
  347           }
  348         }
  349       }
  350     }
  351   }
  352 }

Here's what happens when you run the updated BAT command against the data I used last time:
0.jpg


论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2025-1-6 00:35 , Processed in 0.557372 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表