• Industries
  • Products
  • Buy
  • Services & Support
  • Communities
  • Discussion Groups

    .NET

    Reply
    Active Member
    soccerazy
    Posts: 8
    Registered: ‎10-06-2011
    Accepted Solution

    Add Block When Other Drawings Are Open

    235 Views, 9 Replies
    11-14-2011 09:39 AM

    I'm trying to add a block with an attribute to a drawing. The command works if there is only one drawing open, but when there are other open drawings then the block doesn't appear. Strangely if I select the block in the block editor and then close the block editor the block suddenly appears. Do you know what is causing the block to not appear when other drawings are open?

     

    I included the code below. "s1" works but "s2" has the strange behavior of the block not being visible.

     

    Thanks for any help,

     

    Casey Joyce

     

    [CommandMethod("s1")]
    public void AddBlockWithAttributeToDestination_WithNoOtherDrawingsOpen() {
        var attributeValue = "1234";
        var destination = Application.DocumentManager.MdiActiveDocument;
        using (var transaction = destination.TransactionManager.StartTransaction()) {
            addBlock(transaction, destination.Database, attributeValue);
            transaction.Commit();
        }
    }

    [CommandMethod("s2")]
    public void AddBlockWithAttributeToDestination_WhileSourceDrawingIsOpen() {
        // pretend user selects info from opened source drawing
        var attributeValue = "1234";
        // pretend user selects destination drawing from popup list
        var destinationDrawing = @"c:\destination.dwg";

        // add block to destination drawing
        var destination = Application.DocumentManager.Open(destinationDrawing, false);
        using (var transaction = destination.TransactionManager.StartTransaction()) {
            using (var key = destination.LockDocument()) {
                addBlock(transaction, destination.Database, attributeValue);
            }
            transaction.Commit();
        }
    }

    void addBlock(Transaction transaction, Database database, string attributeValue) {
        // add block
        var block = new BlockTableRecord() { Name = "SampleBlock" };
        var table = transaction.GetObject(database.BlockTableId, OpenMode.ForWrite) as BlockTable;
        var blockId = table.Add(block);
        transaction.AddNewlyCreatedDBObject(block, true);
        // add block reference
        var blockReference = new BlockReference(Point3d.Origin, block.ObjectId);
        var modelSpace = transaction.GetObject(table[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
        modelSpace.AppendEntity(blockReference);
        transaction.AddNewlyCreatedDBObject(blockReference, true);

        // set attribute definition
        var definition = new AttributeDefinition(
            new Point3d(1, 1, 0),
            attributeValue,
            "SampleAttribute",
            "",
            database.Textstyle);
        block.AppendEntity(definition);
        transaction.AddNewlyCreatedDBObject(definition, true);
        // add attribute reference
        var reference = new AttributeReference();
        reference.SetAttributeFromBlock(definition, blockReference.BlockTransform);
        blockReference.AttributeCollection.AppendAttribute(reference);
        transaction.AddNewlyCreatedDBObject(reference, true);
    }

    Please use plain text.
    Distinguished Mentor
    Posts: 839
    Registered: ‎09-07-2004

    Re: Add Block When Other Drawings Are Open

    11-14-2011 03:35 PM in reply to: soccerazy

    Maybe you should lock the document?

     

    Using acLckDoc As DocumentLock = acNewDoc.LockDocument()

    End Using
    Please use plain text.
    Active Member
    soccerazy
    Posts: 8
    Registered: ‎10-06-2011

    Re: Add Block When Other Drawings Are Open

    11-15-2011 01:32 PM in reply to: GTVic

    Thanks for your response GTVic. I am using LockDocument in the s2 command, and that's the one that wasn't working.

    Please use plain text.
    Active Member
    soccerazy
    Posts: 8
    Registered: ‎10-06-2011

    Re: Add Block When Other Drawings Are Open

    11-15-2011 01:35 PM in reply to: soccerazy

    I think I am going to be able to get s2 to work by adding CommandFlags.Session. So far it looks like its working.

     

    [CommandMethod("s2", CommandFlags.Session)]

    Please use plain text.
    Distinguished Mentor
    Posts: 839
    Registered: ‎09-07-2004

    Re: Add Block When Other Drawings Are Open

    11-15-2011 02:15 PM in reply to: soccerazy

    Sorry, didn't notice that, maybe because it was inside the transaction. I think that is a problem, the document should be locked before starting the transaction. That is the way it is documented in the Developer's Guide

     

    CommandFlags.Session might mask the problem. The effect of "Session" is not clear but I take it that nothing else can happen in the application while this command is running and then perhaps there is no need for a lock and the lock being out of order doesn't cause a problem.

    Please use plain text.
    Active Member
    soccerazy
    Posts: 8
    Registered: ‎10-06-2011

    Re: Add Block When Other Drawings Are Open

    11-15-2011 03:12 PM in reply to: GTVic

    I moved the LockDocument outside the transaction as you and the Developer Guide suggested, thanks. When I keep the CommandFlags.Session this seems to work fine. So unless I find a better way I guess I'll stick with this.

     

    Just FYI:

    Even with the lock on the outside of the transaction, the CommandFlags.Session is still required for me to get "s2" to work.

     

    I tried removing the LockDocument all together to see if CommandFlags.Session would take care of it, but it throws an exception in that case.

    Please use plain text.
    Distinguished Mentor
    Posts: 839
    Registered: ‎09-07-2004

    Re: Add Block When Other Drawings Are Open

    11-15-2011 03:33 PM in reply to: soccerazy

    Maybe you need to lock the source drawing, if I'm understanding your code correctly.

     

    This is my subroutine to copy block definitions from a template DWG to the current drawing using the clone method. I use it for updating block definitions or bringing in missing blocks.

     

        Private Sub LoadBlocks()
    
            Dim dm As DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager
            Dim ed As Editor = dm.MdiActiveDocument.Editor
            Dim destDb As Database = dm.MdiActiveDocument.Database
            Dim sourceDb As Database = New Database(False, True)
            Dim mapping As IdMapping = New IdMapping()
            Dim blockIds As ObjectIdCollection = New ObjectIdCollection()
            Dim s As String
            Dim DisplayError As Boolean = False
    
            Try
                Using objLock As DocumentLock = AcadDoc.LockDocument()
                    Try
                        sourceDb.ReadDwgFile(Path.Combine(Path.Combine(EngToolsPath.FullName, "Source"), cboSource.Text), System.IO.FileShare.Read, True, "")
                        Try
                            Using Trans As Transaction = sourceDb.TransactionManager.StartTransaction()
                                Try
                                    Dim bt As BlockTable = Trans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, False)
                                    Dim btr As BlockTableRecord
                                    For Each btrId As ObjectId In bt
                                        btr = Trans.GetObject(btrId, OpenMode.ForRead, False)
                                        If lstItems.SelectedItems.Contains(btr.Name) Then
                                            blockIds.Add(btrId)
                                        End If
                                        btr.Dispose()
                                    Next
                                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                                    ed.WriteMessage(vbLf & "Error scanning for block definitions in source drawing: " & ex.Message & vbLf)
                                    ed.UpdateScreen()
                                    DisplayError = True
                                End Try
                            End Using
                        Catch ex As Autodesk.AutoCAD.Runtime.Exception
                            ed.WriteMessage(vbLf & "Error reading from source drawing: " & ex.Message & vbLf)
                            ed.UpdateScreen()
                            DisplayError = True
                        End Try
                        If Not DisplayError Then
                            Try
                                Using Trans As Transaction = destDb.TransactionManager.StartTransaction()
                                    Try
                                        sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, False)
                                        Trans.Commit()
                                        Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.AcadDocument.Regen(1)
                                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
                                        Trans.Abort()
                                        ed.WriteMessage(vbLf & "Error transferring blocks to current drawing: " & ex.Message & vbLf)
                                        ed.UpdateScreen()
                                        DisplayError = True
                                    End Try
                                End Using
                            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                                ed.WriteMessage(vbLf & "Error transferring blocks to current drawing: " & ex.Message & vbLf)
                                ed.UpdateScreen()
                                DisplayError = True
                            End Try
                        End If
                        sourceDb.Dispose()
                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
                        ed.WriteMessage(vbLf & "Error reading from source drawing: " & ex.Message & vbLf)
                        ed.UpdateScreen()
                        DisplayError = True
                    End Try
                End Using
            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                ed.WriteMessage(vbLf & "Error locking current drawing for update: " & ex.Message & vbLf)
                ed.UpdateScreen()
                DisplayError = True
            End Try
    
            lblError.Visible = DisplayError
    
        End Sub

     

    Please use plain text.
    ADN Support Specialist
    Posts: 261
    Registered: ‎05-22-2006

    Re: Add Block When Other Drawings Are Open

    11-16-2011 08:04 AM in reply to: soccerazy

    BTW (Just checking) Do you actually want to open the document in the editor (i.e. does the user need to see and interact with it). If not, then it is a lot easier (and faster) to open a DWG file in a side database (using Database.ReadDwgFile) to modify it programmatically.

    Cheers,

    Stephen Preston
    Autodesk Developer Network
    Please use plain text.
    Mentor
    Posts: 241
    Registered: ‎05-12-2009

    Re: Add Block When Other Drawings Are Open

    11-16-2011 02:46 PM in reply to: soccerazy

    If you do want them to interact with it have you tried making it the active document first then add Block and BlockReference?

    You can also find your answers @ TheSwamp
    Please use plain text.
    Active Member
    soccerazy
    Posts: 8
    Registered: ‎10-06-2011

    Re: Add Block When Other Drawings Are Open

    11-17-2011 01:25 PM in reply to: soccerazy

    Thanks for everybody's responses. I do need both the source and destination drawing open for the user to interact with. Using the CommandFlags.Session and locking the drawings is working for my situation (at least so far).

    Please use plain text.