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. :-)
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…
… 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):
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.