In this previous post we saw some code to create a table style and apply it to a new table inside an AutoCAD drawing. While responding to a comment on the post, I realised that the table didn't display properly using my example: the first column heading was being taken as the table title and the rest of the column headings were lost - the headings in the table were actually taken from the first row of data. I suppose that serves me right for having chosen such eye-catching (and distracting) colours. :-)
The following C# code addresses this by adding some information to our array of table contents, and using that for the table title. It also does a little more to customize the display of our table by applying chunky lineweights (and yet more garish colours) to the table's grid-lines.
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Colors;
namespace TableAndStyleCreation
{
public class Commands
{
[CommandMethod("CTWS")]
static public void CreateTableWithStyleAndWhatStyle()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptPointResult pr =
ed.GetPoint("\nEnter table insertion point: ");
if (pr.Status == PromptStatus.OK)
{
Transaction tr =
doc.TransactionManager.StartTransaction();
using (tr)
{
// First let us create our custom style,
// if it doesn't exist
const string styleName = "Garish Table Style";
ObjectId tsId = ObjectId.Null;
DBDictionary sd =
(DBDictionary)tr.GetObject(
db.TableStyleDictionaryId,
OpenMode.ForRead
);
// Use the style if it already exists
if (sd.Contains(styleName))
{
tsId = sd.GetAt(styleName);
}
else
{
// Otherwise we have to create it
TableStyle ts = new TableStyle();
// Make the header area red
ts.SetBackgroundColor(
Color.FromColorIndex(ColorMethod.ByAci, 1),
(int)(RowType.TitleRow |
RowType.HeaderRow)
);
// And the data area yellow
ts.SetBackgroundColor(
Color.FromColorIndex(ColorMethod.ByAci, 2),
(int)RowType.DataRow
);
// With magenta text everywhere (yeuch :-)
ts.SetColor(
Color.FromColorIndex(ColorMethod.ByAci, 6),
(int)(RowType.TitleRow |
RowType.HeaderRow |
RowType.DataRow)
);
// And now with cyan outer grid-lines
ts.SetGridColor(
Color.FromColorIndex(ColorMethod.ByAci, 4),
(int)GridLineType.OuterGridLines,
(int)(RowType.TitleRow |
RowType.HeaderRow |
RowType.DataRow)
);
// And bright green inner grid-lines
ts.SetGridColor(
Color.FromColorIndex(ColorMethod.ByAci, 3),
(int)GridLineType.InnerGridLines,
(int)(RowType.TitleRow |
RowType.HeaderRow |
RowType.DataRow)
);
// And we'll make the grid-lines nice and chunky
ts.SetGridLineWeight(
LineWeight.LineWeight211,
(int)GridLineType.AllGridLines,
(int)(RowType.TitleRow |
RowType.HeaderRow |
RowType.DataRow)
);
// Add our table style to the dictionary
// and to the transaction
tsId = ts.PostTableStyleToDatabase(db, styleName);
tr.AddNewlyCreatedDBObject(ts, true);
}
BlockTable bt =
(BlockTable)tr.GetObject(
doc.Database.BlockTableId,
OpenMode.ForRead
);
Table tb = new Table();
tb.NumRows = 6;
tb.NumColumns = 3;
tb.SetRowHeight(3);
tb.SetColumnWidth(15);
tb.Position = pr.Value;
// Use our table style
if (tsId == ObjectId.Null)
// This should not happen, unless the
// above logic changes
tb.TableStyle = db.Tablestyle;
else
tb.TableStyle = tsId;
// Create a 2-dimensional array
// of our table contents
string[,] str = new string[6, 3];
str[0, 0] = "Material Properties Table";
str[1, 0] = "Part No.";
str[1, 1] = "Name";
str[1, 2] = "Material";
str[2, 0] = "1876-1";
str[2, 1] = "Flange";
str[2, 2] = "Perspex";
str[3, 0] = "0985-4";
str[3, 1] = "Bolt";
str[3, 2] = "Steel";
str[4, 0] = "3476-K";
str[4, 1] = "Tile";
str[4, 2] = "Ceramic";
str[5, 0] = "8734-3";
str[5, 1] = "Kean";
str[5, 2] = "Mostly water";
// Use a nested loop to add and format each cell
for (int i = 0; i < 6; i++)
{
if (i == 0)
{
// This is for the title
tb.SetTextHeight(0, 0, 1);
tb.SetTextString(0, 0, str[0, 0]);
tb.SetAlignment(0, 0, CellAlignment.MiddleCenter);
}
else
{
// These are the header and data rows
for (int j = 0; j < 3; j++)
{
tb.SetTextHeight(i, j, 1);
tb.SetTextString(i, j, str[i, j]);
tb.SetAlignment(i, j, CellAlignment.MiddleCenter);
}
}
}
tb.GenerateLayout();
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
btr.AppendEntity(tb);
tr.AddNewlyCreatedDBObject(tb, true);
tr.Commit();
}
}
}
}
}
One other minor enhancement: I made use of the TableStyle.PostTableStyleToDatabase() method to add the style to the appropriate location in the Database (we previously edited the TableStyleDictionary directly to achieve this).
Here's what happens when we run the CTWS command (making sure that we have adjusted the display settings to use lineweights):
And here's the updated style in AutoCAD's TableStyle dialog:
That's better. At least in that it does what was expected of it, even if it's not winning any design awards. :-)
Update
Roland Feletic pointed out that this code - while it still builds for AutoCAD 2011 - causes some "obsolete property/method" compiler warnings. I've provided an updated version of the code below, with the previous lines commented out for comparison:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Colors;
namespace TableAndStyleCreation
{
public class Commands
{
[CommandMethod("CTWS")]
static public void CreateTableWithStyleAndWhatStyle()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptPointResult pr =
ed.GetPoint("\nEnter table insertion point: ");
if (pr.Status == PromptStatus.OK)
{
Transaction tr =
doc.TransactionManager.StartTransaction();
using (tr)
{
// First let us create our custom style,
// if it doesn't exist
const string styleName = "Garish Table Style";
ObjectId tsId = ObjectId.Null;
DBDictionary sd =
(DBDictionary)tr.GetObject(
db.TableStyleDictionaryId,
OpenMode.ForRead
);
// Use the style if it already exists
if (sd.Contains(styleName))
{
tsId = sd.GetAt(styleName);
}
else
{
// Otherwise we have to create it
TableStyle ts = new TableStyle();
// Make the header area red
ts.SetBackgroundColor(
Color.FromColorIndex(ColorMethod.ByAci, 1),
(int)(RowType.TitleRow |
RowType.HeaderRow)
);
// And the data area yellow
ts.SetBackgroundColor(
Color.FromColorIndex(ColorMethod.ByAci, 2),
(int)RowType.DataRow
);
// With magenta text everywhere (yeuch :-)
ts.SetColor(
Color.FromColorIndex(ColorMethod.ByAci, 6),
(int)(RowType.TitleRow |
RowType.HeaderRow |
RowType.DataRow)
);
// And now with cyan outer grid-lines
ts.SetGridColor(
Color.FromColorIndex(ColorMethod.ByAci, 4),
(int)GridLineType.OuterGridLines,
(int)(RowType.TitleRow |
RowType.HeaderRow |
RowType.DataRow)
);
// And bright green inner grid-lines
ts.SetGridColor(
Color.FromColorIndex(ColorMethod.ByAci, 3),
(int)GridLineType.InnerGridLines,
(int)(RowType.TitleRow |
RowType.HeaderRow |
RowType.DataRow)
);
// And we'll make the grid-lines nice and chunky
ts.SetGridLineWeight(
LineWeight.LineWeight211,
(int)GridLineType.AllGridLines,
(int)(RowType.TitleRow |
RowType.HeaderRow |
RowType.DataRow)
);
// Add our table style to the dictionary
// and to the transaction
tsId = ts.PostTableStyleToDatabase(db, styleName);
tr.AddNewlyCreatedDBObject(ts, true);
}
BlockTable bt =
(BlockTable)tr.GetObject(
doc.Database.BlockTableId,
OpenMode.ForRead
);
Table tb = new Table();
tb.InsertRows(0, 3, 6);
tb.InsertColumns(0, 15, 3);
/*
tb.NumRows = 6;
tb.NumColumns = 3;
tb.SetRowHeight(3);
tb.SetColumnWidth(15);
tb.Position = pr.Value;
*/
// Use our table style
if (tsId == ObjectId.Null)
// This should not happen, unless the
// above logic changes
tb.TableStyle = db.Tablestyle;
else
tb.TableStyle = tsId;
// Create a 2-dimensional array
// of our table contents
string[,] str = new string[6, 3];
str[0, 0] = "Material Properties Table";
str[1, 0] = "Part No.";
str[1, 1] = "Name";
str[1, 2] = "Material";
str[2, 0] = "1876-1";
str[2, 1] = "Flange";
str[2, 2] = "Perspex";
str[3, 0] = "0985-4";
str[3, 1] = "Bolt";
str[3, 2] = "Steel";
str[4, 0] = "3476-K";
str[4, 1] = "Tile";
str[4, 2] = "Ceramic";
str[5, 0] = "8734-3";
str[5, 1] = "Kean";
str[5, 2] = "Mostly water";
// Use a nested loop to add and format each cell
for (int i = 0; i < 6; i++)
{
if (i == 0)
{
// This is for the title
tb.Cells[0, 0].TextHeight = 1;
tb.Cells[0, 0].TextString = str[0, 0];
tb.Cells[0, 0].Alignment =
CellAlignment.MiddleCenter;
//tb.SetTextHeight(0, 0, 1);
//tb.SetTextString(0, 0, str[0, 0]);
//tb.SetAlignment(0, 0, CellAlignment.MiddleCenter);
}
else
{
// These are the header and data rows
for (int j = 0; j < 3; j++)
{
tb.Cells[i, j].TextHeight = 1;
tb.Cells[i, j].TextString = str[i, j];
tb.Cells[i, j].Alignment =
CellAlignment.MiddleCenter;
//tb.SetTextHeight(i, j, 1);
//tb.SetTextString(i, j, str[i, j]);
//tb.SetAlignment(i, j, CellAlignment.MiddleCenter);
}
}
}
tb.GenerateLayout();
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
btr.AppendEntity(tb);
tr.AddNewlyCreatedDBObject(tb, true);
tr.Commit();
}
}
}
}
}
Many thanks, Roland! :-)