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            










« Calling unexposed ObjectARX methods using P/Invoke from .NET | Main | New self-paced AutoCAD .NET training material »

May 04, 2011

Copying rows between AutoCAD tables using .NET

Thanks to Marat Mirgaleev, a member of our DevTech team based in Moscow, for the code that inspired this post.

The code in this post implements the simple case of taking the last two rows of one table and copying them into the same relative position in another table. If the destination table is smaller, it gets expanded, as do the individual rows  and columns.

Other than that, there’s not much to it. I have tried to structure the code to make it easy to adapt to more “challenging” tasks, such as taking an arbitrary, rectangular selection of cells and copying them across to another table (even a new one). This gets more into the selection side of things – and may even involve a combination of sub-entity selection and transient graphics, we’ll see – it should certainly be fun. :-)

Here’s the C# code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

 

namespace TableCopying

{

  public class Commands

  {

    [CommandMethod("CRBT")]

    public static void CopyRowsBetweenTables()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;

 

      try

      {

        // Ask the user to select the two tables

 

        PromptEntityOptions peo =

          new PromptEntityOptions("\nSelect source table");

        peo.SetRejectMessage("\nMust be a table.");

        peo.AddAllowedClass(typeof(Table), false);

        peo.AllowNone = false;

        PromptEntityResult per = ed.GetEntity(peo);

        if (per.Status != PromptStatus.OK)

          return;

 

        ObjectId srcId = per.ObjectId;

 

        peo.Message = "\nSelect destination table";

        per = ed.GetEntity(peo);

        if (per.Status != PromptStatus.OK)

          return;

 

        ObjectId destId = per.ObjectId;

 

        Transaction tr =

          doc.TransactionManager.StartTransaction();

        using (tr)

        {

          // Open the tables: one for read, one for write

 

          Table srcTab =

            tr.GetObject(srcId, OpenMode.ForRead) as Table;

          Table destTab =

            tr.GetObject(destId, OpenMode.ForWrite) as Table;

 

          if (srcTab == null || destTab == null)

            return;

 

          // Make sure the destination table has enough rows...

 

          if (destTab.Rows.Count < srcTab.Rows.Count)

          {

            destTab.InsertRows(

              destTab.Rows.Count,

              5, // An arbitrary row height

              srcTab.Rows.Count - destTab.Rows.Count

            );

          }

 

          // ... and columns

 

          if (destTab.Columns.Count < srcTab.Columns.Count)

          {

            destTab.InsertColumns(

              destTab.Columns.Count,

              25, // An arbitrary column width

              srcTab.Columns.Count - destTab.Columns.Count

            );

          }

 

          // Copy the last two rows from the source table to

          // the destination table

 

          int nRows = 2, // Number of rows to copy

              nCols = srcTab.Columns.Count, // and columns

 

              // Source column and row numbers

 

              srcFirstCol = 0,

              srcLastCol = nCols - 1,

              srcLastRow = srcTab.Rows.Count - 1,

              srcFirstRow = srcLastRow - nRows + 1,

 

              // Destination column and row numbers

              // (for now the same as the source ones)

 

              destFirstCol = srcFirstCol,

              destFirstRow = srcFirstRow,

              destLastCol = srcLastCol,

              destLastRow = srcLastRow;

 

          destTab.CopyFrom(

            srcTab,

            TableCopyOptions.FillTarget,

            CellRange.Create(

              srcTab,

              srcFirstRow, srcFirstCol,

              srcLastRow, srcLastCol

            ),

            CellRange.Create(

              destTab,

              destFirstRow, destFirstCol,

              destLastRow, destLastCol

            )

          );

 

          destTab.GenerateLayout();

 

          // Make sure the columns of data we copied

          // across have the same width as the source

 

          for (int i = 0; i < nCols; i++)

          {

            if (

              destTab.Columns[destFirstCol + i].Width <

                srcTab.Columns[srcFirstCol + i].Width

            )

            {

              destTab.Columns[destFirstCol + i].Width =

                srcTab.Columns[srcFirstCol + i].Width;

            }

          }

 

          // Do the same for the row heights

 

          for (int r = 0; r < nRows; r++)

          {

            if (

              destTab.Rows[destFirstRow + r].Height <

                srcTab.Rows[srcFirstRow + r].Height

            )

            {

              destTab.Rows[destFirstRow + r].Height =

                srcTab.Rows[srcFirstRow + r].Height;

            }

 

            // And match the cell styles, etc.

 

            for (int c = 0; c < nCols; c++)

            {

              CellRange srcCell =

                srcTab.Cells[

                  srcFirstRow + r, srcFirstCol + c

                ];

              CellRange destCell =

                destTab.Cells[

                  destFirstRow + r, destFirstCol + c

                ];

              if (srcCell.Style != null)

                destCell.Style = srcCell.Style;

              if (srcCell.TextHeight > 0)

                destCell.TextHeight = srcCell.TextHeight;

              if (srcCell.TextStyleId != null)

                destCell.TextStyleId = srcCell.TextStyleId;

              if (srcCell.Alignment != null)

                destCell.Alignment = srcCell.Alignment;

            }

          }

          tr.Commit();

        }

      }

      catch (Autodesk.AutoCAD.Runtime.Exception ex)

      {

        ed.WriteMessage("\nException: {0}", ex.Message);

      }

    }

  }

}

Let’s see what happens when we use our CRBT (CopyRowsBetweenTables) command to select and copy contents from these source tables from the “Mechanical Samples\Mechanical - Text and Tables.dwg” sample drawing…

Source tables

… into the destination tables next to them (which you can see as dots in the above image – they are at a relatively very small scale):

Copied contents in expanded destination tables

I was initially confused as to why the CRBT command only copied one row from the left-most table: it took me some time to figure out that the bottom two rows of that table are actually merged. So the code is indeed working as expected.

blog comments powered by Disqus

Feed/Share

10 Random Posts