Hi All,
I am wondering if someone can help me figure out what I am doing wrong. I have code that reads mleader info from a drawing and inputs the data into a table. Before it does that, the code unlocks the layer that the table is on. After I am done editing the table, I relock the layer the table is on. For some reason, when I relock the layer, the boudary lines of the table all shift. The data stays in the proper location (see attached image).
I am still able to edit the table (after unlocking the layer) and if I close the drawing and reopen it, the table goes back to normal.
If I comment out the code that I have to lock the table, the problem does not occur.
Here is my code:
Dim acLayName As String = "ANO-TABLES" Dim acLyrTbl As LayerTable = TryCast(acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite, False), LayerTable) If acLyrTbl Is Nothing Then Return End If Dim acLayTblRec As LayerTableRecord For Each objId As ObjectId In acLyrTbl acLayTblRec = objId.GetObject(OpenMode.ForRead) If acLyrTbl.Has(acLayName) Then acLayTblRec.UpgradeOpen() '' Unlock layer table record If acLayTblRec.IsLocked = True Then acLayTblRec.IsLocked = False End If End If Next '' Do stuff to table here '' Relock layertable record acLayTblRec.IsLocked = True
Any ideas???
Thanks
Solved! Go to Solution.
Solved by Artvegas. Go to Solution.
I'm not sure about why the table is not updating correctly as it's difficult to replicate from what you have provided, but I had the following comments:
1. Are you aware that you can edit a graphical entity using the .NET API, even if it is on a locked layer? I suppose I'm wondering why you are unlocking and locking the layer? If you are editing the table programatically you shouldn't need to do this.
2. Have you tried switching back and forth between model and paper space layouts, i.e.:
acCurDb.TileMode = !acCurDb.TileMode
acCurDb.TileMode = !acCurDb.TileMode
Sometimes this helps regen a view.
3. I am confused by your sample. You appear to be opening the LayerTable and then iterating each ObjectId as follows:
- opening each LayerTableRecord for read
- checking whether the LayerTable has a "ANO-TABLES" layer (which assuming this layer exists, will ALWAYS return true)
- upgrading each LayerTableRecord for write
- unlocking each LayerTableRecord
And then after the loop has finished you appear to lock only the last LayerTableRecord from the loop.
Hope this helps.
Art.
To add to what Art posted,
You can think of
LayerTable("LayerName") for VB or
LayerTable["LayerName"] for C#
as Indexer Methods which allow access to internal subitems using array-like syntax
Passing in the name of the layer will return its ObjectId so something like this
Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim layerName As String = "LayerName" Using trx As Transaction = db.TransactionManager.StartTransaction() Dim bt As BlockTable = trx.GetObject(db.BlockTableId, OpenMode.ForRead) Dim currentSpace As BlockTableRecord = trx.GetObject(db.CurrentSpaceId, OpenMode.ForRead) Dim layerTbl As LayerTable = trx.GetObject(db.LayerTableId, OpenMode.ForRead) If layerTbl.Has(layerName) Then Dim layerTblRecord As LayerTableRecord = trx.GetObject(layerTbl(layerName), OpenMode.ForWrite) layerTblRecord.IsLocked = False End If trx.Commit() End Using
Also as Art mentioned one of the overloaded versions of GetObject takes a boolean as a parameter if you want to force objects on Locked layers to be opened.
Hi guys!
Thanks for calling me out on my poor coding abilities! I need all the advice I can get as I still have a TON to learn! Most of the code I write is loosley based on an examples I find in books, online or from the forums.
I did not realize that you could force objects on locked layers to be opened, hence the reason I was unlocking the layer first. I have re-written the code to no longer touch the layers. Now I simply unlock the table with an overload of GetObjects.
After running the code again, I am unfortuantely still seeing the same table behaviour. A regen does not bring it back and switching tile mode in my code does not bring it back. The only thing that seems to correct it is closing and reopening the drawing. Am I doing something wrong in the way I am editing the table? If the layer is not locked when the code is run, then the problem does not occur.
Here is my full code:
<CommandMethod("ECDT_NWDataToTable")> _ Public Sub ECDT_NWDataToTable() '' Declare the current document, database and editor Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument Dim acCurDb As Database = acDoc.Database Dim acEd As Editor = DocumentManager.MdiActiveDocument.Editor '' Start a transaction Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction() Try Dim acBt As BlockTable = acDoc.Database.BlockTableId.GetObject(OpenMode.ForRead) Dim acBtrMs As BlockTableRecord = DirectCast(acBt(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForRead), BlockTableRecord) Dim myLeadVals As New List(Of String) Dim myLeadQtys As New List(Of String) Dim Splits As String() = Nothing '' Get embed (BOM) multileader contents For Each objId As ObjectId In acBtrMs Dim acMlead As MLeader = TryCast(acTrans.GetObject(objId, OpenMode.ForRead), MLeader) If acMlead IsNot Nothing Then Dim MleadStyle As MLeaderStyle = acTrans.GetObject(acMlead.MLeaderStyle, OpenMode.ForRead) Dim strMlStyle As String = MleadStyle.Name If strMlStyle = "ECDT_ANO_NW-BoM" Then Dim strMtextValue As String strMtextValue = acMlead.MText.Text Splits = strMtextValue.Split(New [Char]() {"'"c, "-"c, ChrW(39), ChrW(34), ChrW(13)}, StringSplitOptions.RemoveEmptyEntries) myLeadQtys.Add(Splits(0)) myLeadVals.Add(Splits(1)) If myLeadQtys.Count > 21 Then MsgBox("Too many BoM tags for data table! Remove tag(s) and try again.", , "Data Error") Exit Sub End If End If End If Next '' Open table and add multileader values to table Dim acBtrPs As BlockTableRecord = DirectCast(acBt(BlockTableRecord.PaperSpace).GetObject(OpenMode.ForRead), BlockTableRecord) For Each objId As ObjectId In acBtrPs Dim acTable As Table = TryCast(acTrans.GetObject(objId, OpenMode.ForWrite, False, True), Table) If acTable IsNot Nothing Then Dim strTblStylName As String = acTable.TableStyleName If strTblStylName = "ECDT_NW-BillofMaterials" Then Dim range As CellRange = CellRange.Create(acTable, 2, 0, 22, 1) range.DeleteContent() Dim iCnt As Integer = myLeadQtys.Count + 2 Dim j As Integer = 0 For i As Integer = 2 To iCnt - 1 acTable.Cells(i, 0).TextString = myLeadQtys(j) acTable.Cells(i, 1).TextString = myLeadVals(j) j = j + 1 Next acTable.DowngradeOpen() End If End If Next acCurDb.TileMode = Not acCurDb.TileMode acCurDb.TileMode = Not acCurDb.TileMode Catch ex As Autodesk.AutoCAD.Runtime.Exception MsgBox("An error has occured. Please contact you system administrator." & vbCr & vbCr & ex.Message & vbCr & ex.StackTrace) Finally End Try acTrans.Commit() End Using End Sub
I am also attaching a sample drawing where the issue occurs.
Thanks for your help!
I ran your code and dwg in AutoCAD 2012 and I see what you mean. When the layer is locked the table cell borders go weird!!
I tried a number of different techniques to try to regenerate the table but none seemed to work. I tried to unlock the layer within the command, change the table, and then re-lock the layer. Still to no avail.
Welcome to strange happenings in the world of the AutoCAD API
Below is my suggested workaround. Although not ideal, it does work!
The approach here is to create seperate commands to do the following:
1. Unlock the layer if it is locked.
2. Update the table.
3. Re-lock the layer if it was originally locked.
4. Create a command to send the commands in 1-3 to the command-line.
An outline of these commands would be as follows:
'***********************************************************************************************************
Public Class CommandClass
'Class level variable
Dim isLayerLocked As Boolean = False
<CommandMethod("UnlockLayer", CommandFlags.NoUndoMarker)>
Public Sub UnlockLayer()
'If layer is locked, set isLayerLocked variable to True and unlock the layer.
End Sub
<CommandMethod("UpdateTable", CommandFlags.NoUndoMarker)>
Public Sub UpdateTable ()
‘Update table.
End Sub
<CommandMethod("ReLockLayer", CommandFlags.NoUndoMarker)>
Public Sub ReLockLayer ()
‘Check isLayerLocked variable, and if True then re-lock the layer.
End Sub
<CommandMethod("ECDT_NWDataToTable")>
Public Sub ECDT_NWDataToTable()
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
‘Send commands to command-line.
doc.SendStringToExecute("UnlockLayer UpdateTable LockLayer ", False, False, False)
End Sub
End Class
'***********************************************************************************************************
Notes:
1. The UnlockLayer, UpdateTable and ReLockLayer commands have the CommandFlags.NoUndoMarker in command attribute.
I've done this so that if the user wants to UNDO the ECDT_NWDataToTable command, they won't have to perform repeated
undos for each of the sub-commands.
2. The echoCommand parameter in the SendStringToExecute() method is set to False, so that the user will only see
ECDT_NWDataToTable in the command-line.
Hope this helps.
Art
Hey Art! This is great stuff! Works great!
Too bad about the table not updating properly. Seems to be a bug of sorts? Do you know if there is a procedure that differs from the regular method for AutoCAD bug reporting (Product Feedback Form) to get this info to Autodesk so they can look into it?
Thanks for all of your help! I will accept your post as the solution, but if you (or anyone else) discover how to get the table to update properly, please let me know!
Thanks again!
Hi,
I had another look and this issue also seems to be related to how your table and its table style is formatted.
Please refer to the attached ModifiedTest.dwg (AutoCAD 2010 dwg format).
I added a new ECDT_NW-BillofMaterials table to the locked layer using the TABLE command. I left the 'Insert Table' dialog defaults and hit OK.. Refer to the attached InsertTableDialog.jpg image which shows the default settings I used.
Now when I update the tables (with the layer locked), the one I inserted from scratch works fine but the one you had loses its borders. Refer to the attached Screenshot.jpg image which shows the results.
Might be worth spending some time looking into your table and the table style you're using.
Cheers,
Art
p.s. I believe the only way you could get this directly addressed by Autodesk is by subscribing to the Autodesk Developer Network, of which I am not a member: http://autodesk.com/developer