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,

        &#
160;     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 <

         
0;      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.

8 responses to “Copying rows between AutoCAD tables using .NET”

  1. Hi,there!
    I'd like to ask a favor that how could I get the extents of a MgCurveString object in Civil3D.
    I had found some information that the MgCurveString object had a member called Boundary(), but this member could not gave me the perfect extents of MgCurveSting object sometimes.
    Do you have any other way to fit my problem?
    Thank you very much.
    Tomans.

  2. Kean Walmsley Avatar
    Kean Walmsley

    Hi Tomans,

    Sorry - this isn't a forum for support, and I don't work with the Civil 3D API, myself.

    Please address your question to ADN or the discussion groups.

    Regards,

    Kean

  3. All right.
    Anyway , thank you very much.

  4. Hi Kean,
    I would like to ask how to use layertable to change all layers'colors to the same color?

    [CommandMethod("changeLayerColors")]
    public static void changeLayerColors()
    {
    Database db = HostApplicationServices.WorkingDatabase;
    using (Transaction trans = db.TransactionManager.StartTransaction())
    {
    LayerTable It = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
    foreach (ObjectId layerId in It)
    {
    LayerTableRecord Itr = (LayerTableRecord)trans.GetObject(layerId, OpenMode.ForWrite);
    Color layerColor = Color.FromColorIndex(ColorMethod.ByColor, 1);
    Itr.Color = layerColor;
    }
    trans.Commit();
    }
    }

    Above is my program, but no effect after load, do you know what's wrong?
    Thank you very much!
    Nathan.

  5. Kean Walmsley Avatar
    Kean Walmsley

    Hi Nathan,

    This isn't a forum for support.

    Your comment doesn't appear to relate to this post, so please submit your question to the ADN team, if you're a member, or otherwise the AutoCAD .NET Discussion Group.

    Kean

  6. thank you very much!

  7. André Dagenais Avatar
    André Dagenais

    Hi,

    Is it possible to select the rows to be copied?

    Regards,
    André

    1. Sure, but that's certainly beyond the scope of this post.

      The easiest would be to ask for row numbers and then highlight them in the table to confirm... but you could ask for cells/rows to be picked, otherwise.

      Kean

Leave a Reply

Your email address will not be published. Required fields are marked *