November 2014

Sun Mon Tue Wed Thu Fri Sat
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            










« Creating a simple associative AutoCAD array along a path using .NET | Main | Navigating an AutoCAD model using Kinect – Part 1 »

November 04, 2011

Handling protocol changes to AutoCAD’s table in .NET

This question came up, from our friends over at The Swamp:

I have been re-building some old code  in VS2010 using the 2012 ObjectARX SDK and came across some
     '
blablabla is obsolete: use thingy instead' warnings.

The code still compiles and runs fine but I want to start thinking about the future.

a few examples will follow, please add any others you come across.

[…]

The next was to do with the Table Class
i.e.  Autodesk.AutoCAD.DatabaseServices.Table

In fact, there are a myriad of obsolete warnings in the Table class  ... some of them appear to have no documented resolution, some appear to not work using the suggested resolution.

As Kerry said, further down the thread, he felt it was time to “phone a friend”, which I assume (or hope) means me (although he did email rather than phone me :-). In looking into this, I had some help from Stephen Preston (who pointed me at some information previously provided by Philippe Leefsma and Balaji Ramamoorthy, which helped a great deal).

Let’s focus on the changes to the Table protocol that now (and I’m not sure when exactly it changed – perhaps in AutoCAD 2009?) results in warnings in posts such as this one.

To illustrate some of the main changes in the Table API, I’ve created some C# code that creates two identical tables, one using the old approach and one using the newer, non-deprecated protocol:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;

using System;

 

namespace TableCreation

{

  public class Commands

  {

    [CommandMethod("TWOTABLES")]

    public void CreateTwoTables()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

 

      Transaction tr =

        doc.TransactionManager.StartTransaction();

 

      using (tr)

      {

        // Set some constants that we'll use to create our tables

 

        const int numRows = 7;

        const int numCols = 5;

        const double rowHeight = 3;

        const double colWidth = 3;

        const double horMarg = 0.5;

        const double verMarg = 0.8;

        const double txtHeight = 1;

 

        // We'll add our tables to the current space

 

        BlockTableRecord btr =

          (BlockTableRecord)tr.GetObject(

            db.CurrentSpaceId,

            OpenMode.ForWrite

          );

 

        // We'll use scoping to let us use the same variable

        // name(s) for both tables we're creating

 

        {

          // Create a table with the old protocol

 

          Table tb = new Table();

          tb.TableStyle = db.Tablestyle;

 

          // Resize the table, adding rows and columns

 

          tb.NumRows = numRows;

          tb.NumColumns = numCols;

 

          // Set the column width and row height

 

          tb.SetColumnWidth(colWidth);

          tb.SetRowHeight(rowHeight);

 

          // Set the horizontal and vertical margins

 

          tb.HorizontalCellMargin = horMarg;

          tb.VerticalCellMargin = verMarg;

 

          // Make sure the header and title rows are visible

 

          tb.IsHeaderSuppressed = false;

          tb.IsTitleSuppressed = false;

 

          // Set the title string

 

          tb.SetTextString(0, 0, "Old Table");

 

          // Set the text height for the full table: value of 7

          // is bit-encoded Data (1), Title (2) and Header (4)

 

          tb.SetTextHeight(txtHeight, 7);

 

          // Populate the contents of the header and data sections

 

          int n = 0;

          for (int i = 1; i < numRows; i++)

          {

            for (int j = 0; j < numCols; j++)

            {

              // Contents is A-E for the header an 0-n for the data

 

              string contents =

                (i == 1 ?

                  Convert.ToChar(

                    Convert.ToInt16('A') + j

                  ).ToString() :

                  n++.ToString()

                );

 

              tb.SetTextString(i, j, contents);

            }

          }

 

          tb.GenerateLayout();

 

          btr.AppendEntity(tb);

          tr.AddNewlyCreatedDBObject(tb, true);

        }

 

        {

          // Create a table with the new protocol

 

          Table tb = new Table();

          tb.TableStyle = db.Tablestyle;

 

          // Set the height and width of the initial row and

          // column belonging by default to the blank Table

 

          tb.Rows[0].Height = rowHeight;

          tb.Columns[0].Width = colWidth;

 

          // Add the remaining rows and columns

 

          tb.InsertRows(1, rowHeight, numRows - 1);

          tb.InsertColumns(1, colWidth, numCols - 1);

 

          // To query the number of rows and columns...

          //

          // int nRows = tb.Rows.Count;

          // int nCols = tb.Columns.Count;

 

          // To "suppress" the title and header, find the row

          // with a style of "Title" or "Header" and set it to ""

 

          tb.Cells[0, -1].Style = "Title";

          tb.Cells[1, -1].Style = "Header";

 

          // Add the contents of the Title cell

 

          Cell tc = tb.Cells[0, 0];

 

          tc.Contents.Add();

          tc.Contents[0].TextHeight = txtHeight;

          tc.Contents[0].TextString = "New Table";

 

          // Populate the contents of the header and data sections

 

          int n = 0;

          for (int i = 1; i < numRows; i++)

          {

            for (int j = 0; j < numCols; j++)

            {

              // Contents is A-E for the header an 0-n for the data

 

              string contents =

                (i == 1 ?

                  Convert.ToChar(

                    Convert.ToInt16('A') + j

                  ).ToString() :

                  n++.ToString()

                );

 

              Cell c = tb.Cells[i, j];

 

              // Set the text contents of the cell

 

              c.Contents.Add();

              c.Contents[0].TextHeight = txtHeight;             

              c.Contents[0].TextString = contents;

 

              // Set the horizontal margins

 

              c.Borders.Left.Margin = horMarg;

              c.Borders.Right.Margin = horMarg;

 

              // Set the vertical margins

 

              c.Borders.Top.Margin = verMarg;

              c.Borders.Bottom.Margin = verMarg;

            }

          }

 

          // We'll separate this table from the first one

 

          tb.Position = new Point3d(20, 0, 0);

 

          tb.GenerateLayout();

 

          btr.AppendEntity(tb);

          tr.AddNewlyCreatedDBObject(tb, true);

        }

 

        tr.Commit();

      }

    }

  }

}

Before we take a look at  the changes needed to the first code to get the second, let’s see the warnings generated by the first code section when we build the project in Visual Studio (I’ve removed the Autodesk.AutoCAD.DatabaseServices. namespace prefix from each of the following lines):

'Table.NumRows' is obsolete: 'Use Table.Rows.Count instead.'

'Table.NumColumns' is obsolete: 'Use Table.Columns.Count instead.'

'Table.HorizontalCellMargin' is obsolete: 'Use Table.Cells[row, column].HorizontalLine.Margin instead.'

'Table.VerticalCellMargin' is obsolete: 'Use Table.Cells[row, column].VerticalLine.Margin instead.'

'Table.IsHeaderSuppressed' is obsolete: 'Use Cell functionality instead.'

'Table.IsTitleSuppressed' is obsolete: 'Use Cell functionality instead.'

'Table.SetTextString(int, int, string)' is obsolete: 'Use Table.Cells[row,column].TextString instead.'

'Table.SetTextHeight(double, int)' is obsolete: 'Use Cell functionality instead.'

'Table.SetTextString(int, int, string)' is obsolete: 'Use Table.Cells[row,column].TextString instead.'

The first warnings, related to the changing the size of the table, are straightforward enough to fix (when querying, it’s possible to follow the advice to use Table.Rows.Count and Table.Columns.Count: when resizing the table, we need to use the appropriate methods to insert/delete rows/columns at the right place, which actually makes more sense than arbitrarily setting the number of rows and columns to new values.

The second set of warnings, which cover setting the cell margins, are a little trickier to address (the suggestion to use the HorizontalLine and VerticalLine properties is misleading). Yes, you need to set the appropriate property for a specific cell, but the way you access the property is a little different – you need to use the Borders property to get access to the appropriate margin.

The good news is that there’s much finer control now possible: you can set left/right/top/bottom margins rather than having to live with equal margins in horizontal and vertical directions.

Next we have the third set of warnings, which relate to suppression of the title and header rows. These are also at the Cell level, but are also a bit tricky to get access to. You need to get the Cells for the row (passing in the row number and -1, for the column) and get/set the Style property. This string property should contain “Title” for title rows and “Header” for header rows. If you want to suppress the title – the equivalent of Table.IsTitleSuppressed = true), you can search through for the row containing “Title” in its Style property, and set it to the empty string (“”). And the equivalent operation for the header row.

Finally, we have the methods to set the size and contents of the text string for a cell. For this, you need to add a new item to the Contents collection for a cell, and from that you can set the text string and its height, as before.

Just to show that we have similar tables – at least with the properties I’ve assigned: there may be things I’ve missed when passing in different values for text sizes, margins, etc. – here are the results of running the TWOTABLES command:

Tables created using old and new protocols

blog comments powered by Disqus

Feed/Share

10 Random Posts