- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I have this piece of code, that takes the BlockTableRecord of a Layout, and inserts a Table that is passed in, as well as inserts a new Block and updates Attributes inside the block.
public static void UpdateLayoutBtr(BlockTableRecord btr, Transaction tran, Table table, MyDataObject data)
{
Point3d tableInsertPoint = table.Position;
if (btr == null) return;
btr.AppendEntity(table);
tran.AddNewlyCreatedDBObject(table, true);
//inserts MText above inserted Table
InsertNote(btr, tran, tableInsertPoint);
//Erases old block
RemoveOldBlock(btr, tran);
//finds block in block table and inserts into BTR, then updates attributes
MyBlock.InsertNewBlock(
btr,
tableInsertPoint.Add(new Vector3d(2.8694, .69, 0)),
data);
}
public static void InsertNewBlock(BlockTableRecord btr, Point3d insertPoint, MyDataObject data)
{
ObjectId blockId = ObjectId.Null;
using (Transaction tr = btr.Database.TransactionManager.StartOpenCloseTransaction())
{
try
{
blockId = Active.Database.InsertIntoBlockTableRecord(
BlockNameCustomGrooveCount,
insertPoint,
layerName: "My_Layer",
modelOrPaper: btr,
transaction: tr);
if (blockId == ObjectId.Null) return;
tr.Commit();
}
catch (Exception ex)
{
Active.WriteMessage($"Error in {nameof(MyBlock)}.{nameof(InsertNewBlock)}: {ex.Message}");
tr.Abort();
}
}
if(blockId == ObjectId.Null) return;
FillAttributes(blockId, results);
}
private static void FillAttributes(ObjectId tableId, MyDataObject results)
{
using (Transaction tr = tableId.Database.TransactionManager.StartOpenCloseTransaction())
using(BlockReference br = tr.GetObject(tableId, OpenMode.ForWrite, false, true) as BlockReference)
{
if (br == null) return;
//Format the total length of lines
string slineLengths = Converter.DistanceToString(results.LineLength, DistanceUnitFormat.Architectural, 0);
foreach (ObjectId attId in br.AttributeCollection)
{
using (AttributeReference attRef =
tr.GetObject(attId, OpenMode.ForWrite, false, true) as AttributeReference)
{
switch (attRef.Tag)
{
case "Turns:": attRef.TextString = results.ArcCount.ToString(); break;
case "Length:": attRef.TextString = slineLengths; break;
default: break;
}
}
}
}
}
And this is the code that generates the Table that is passed in to UpdateLayoutBtr
public static Table Update(Transaction tr, Layout layout, MyDataCollection tableData)
{
if (layout == null) return null;
ObjectIdCollection tableIds = layout.GetTableIds(Title);
if (tableIds == null || tableIds.Count == 0) return null;
Point3d oldPosition = Point3d.Origin;
int oldCount = 0;
using (Table oldTable = tr.GetObject(tableIds[0], OpenMode.ForWrite, false, true) as Table)
{
if (oldTable == null) return null;
oldPosition = oldTable.Position;
oldCount = oldTable.Rows.Count-3; //3 rows are Title, headers, bottom row
oldTable.Erase();
}
//Point3d insertPoint = scheduleInsertPoint(tableData.Count - oldCount, oldPosition);
Point3d insertPoint = oldPosition;
if (insertPoint == Point3d.Origin) return null;
Table tb = BuildTable(Title, HEADERS, insertPoint, tableData);
tb.Layer = LayerName;
tb.Color = Color.FromColorIndex(ColorMethod.ByAci, 0);
return tb;
}
public static Table BuildTable(string title, List<string> headers, Point3d insertPoint, MyDataCollection tableData)
{
/*
*Table gets created with default 1 row and 1 column
* so when inserting default rows and columns, remove old row and column
* which get pushed to the last index
*/
Table tb = new Table();
try
{
tb.Position = insertPoint;
tb.Layer = LayerName;
tb.TableStyle = Active.Database.Tablestyle;
int titleRow = 0, headersRow = 1, totalRow = 2;
tb.InsertColumns(0, 1.5, 4);
tb.DeleteColumns(tb.Columns.Count - 1, 1);//deletes the default column
tb.SetColumnWidth(1.5);
tb.Columns[1].Width = 1.63;
tb.Columns[2].Width = 1;
tb.InsertRows(0, .5, 3);
tb.DeleteRows(tb.Rows.Count - 1, 1);
tb.SetRowHeight(.5);
tb.Cells.TextHeight = .19;//main text height
//Title row
CellRange titleRange = CellRange.Create(tb, titleRow, 0, titleRow, 3);
tb.MergeCells(titleRange);
tb.Rows[titleRow].TextHeight = .25;//bigger title
tb.Cells[titleRow, 0].TextString = title;
tb.Rows[titleRow].Alignment = CellAlignment.MiddleCenter;
//headers row
tb.Cells[headersRow, zoneCol].TextString = "FIRST";
tb.Cells[headersRow, manifoldCol].TextString = "SECOND";
tb.Cells[headersRow, loopCol].TextString = "THIRD";
tb.Cells[headersRow, lengthCol].TextString = "FOURTH";
tb.Rows[headersRow].Alignment = CellAlignment.MiddleCenter;
foreach (MyData data in tableData)
{
int row = tb.Rows.Count - 1;
tb.InsertRows(row, .38, 1);
tb.Cells[row, 0].SetValue(data.First, ParseOption.SetDefaultFormat);
tb.Cells[row, 1].SetValue(data.Second, ParseOption.SetDefaultFormat);
tb.Cells[row, 2].SetValue(data.Third, ParseOption.SetDefaultFormat);
tb.Cells[row, 3].TextString = data.Fourth;
}
//total row
int bottomRow = tb.Rows.Count - 1;
tb.Cells[bottomRow, manifoldCol].TextString = "TOTAL";
tb.Cells[tb.Rows.Count - 1, 3].Contents.Add();
tb.Cells[tb.Rows.Count - 1, 3].Contents[0].Formula = "=Sum(D3:D" + (tb.Rows.Count - 1) + ")";
tb.GenerateLayout();
}
catch (Exception ex)
{
Active.WriteMessage($"\nError in {nameof(BuildTable)}: {ex.Message}");
return null;
}
return tb;
}
There is already a Table in the layout with the proper Title, which is a const string. I delete that Table and then insert the new one.
So here is the weird part. If I run this code like this the Table gets inserted, but only has the Title, Headers, and Total rows. None of the data added in the foreach loop. Though when I'm in the debugger, I DO see the rows added. I make sure that the Table getting added to the Layout is the same one built, and it is, with the proper amount of rows as I would expect from the data passed to the Table builder. But once the operation ends, like I say above, the Table does not come out as I would expect, it does not have the data rows.
The Block I insert also does not have the attributes edited.
After so much debugging and trying weird things I came across two weird situations. If I change
//Title is a readonly const string
Table tb = BuildTable(Title, HEADERS, insertPoint, tableData);
to
Table tb = BuildTable("Test", HEADERS, insertPoint, tableData);
Both the Table and Block come out updated in AutoCAD. This will delete the Table that already exists in the Layout with the proper Title, and replace it with a new one with a Title reading "Test".
If I leave the Table title alone, back to the original. If I instead comment out appending appending and adding the new Table
//btr.AppendEntity(table);
//tran.AddNewlyCreatedDBObject(table, true);
The old Table gets deleted as expected, and the new one does not appear, which is also expected. But the Block will now be updated??
I'm at a loss for what to do, any help would be greatly appreciated
Solved! Go to Solution.